19fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan/* 2aadd6fad3f09bd5abcaacf8618fb8093a5aa7ba8Andrew Morgan * Copyright (c) 1999,2007 Andrew G. Morgan <morgan@kernel.org> 39fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * 49fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * The purpose of this module is to enforce inheritable capability sets 59fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * for a specified user. 69fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan */ 79fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 89fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan/* #define DEBUG */ 99fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 109fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <stdio.h> 119fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <string.h> 129fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <errno.h> 139fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <stdarg.h> 14aadd6fad3f09bd5abcaacf8618fb8093a5aa7ba8Andrew Morgan#include <stdlib.h> 15aadd6fad3f09bd5abcaacf8618fb8093a5aa7ba8Andrew Morgan#include <syslog.h> 169fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 179fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <sys/capability.h> 189fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 199fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <security/pam_modules.h> 209fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#include <security/_pam_macros.h> 219fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 229fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#define USER_CAP_FILE "/etc/security/capability.conf" 239fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#define CAP_FILE_BUFFER_SIZE 4096 249fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#define CAP_FILE_DELIMITERS " \t\n" 259fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#define CAP_COMBINED_FORMAT "%s all-i %s+i" 269fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#define CAP_DROP_ALL "%s all-i" 279fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 289fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganstruct pam_cap_s { 299fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int debug; 309fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan const char *user; 319fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan const char *conf_filename; 329fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan}; 339fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 349fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan/* obtain the inheritable capabilities for the current user */ 359fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 369fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganstatic char *read_capabilities_for_user(const char *user, const char *source) 379fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan{ 389fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char *cap_string = NULL; 399fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char buffer[CAP_FILE_BUFFER_SIZE], *line; 409fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan FILE *cap_file; 419fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 429fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_file = fopen(source, "r"); 439fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (cap_file == NULL) { 449fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("failed to open capability file")); 459fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return NULL; 469fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 479fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 489fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan while ((line = fgets(buffer, CAP_FILE_BUFFER_SIZE, cap_file))) { 499fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int found_one = 0; 509fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan const char *cap_text; 519fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 529fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_text = strtok(line, CAP_FILE_DELIMITERS); 539fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 549fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (cap_text == NULL) { 559fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("empty line")); 569fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan continue; 579fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 589fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (*cap_text == '#') { 599fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("comment line")); 609fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan continue; 619fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 629fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 63aadd6fad3f09bd5abcaacf8618fb8093a5aa7ba8Andrew Morgan while ((line = strtok(NULL, CAP_FILE_DELIMITERS))) { 649fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 659fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (strcmp("*", line) == 0) { 669fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("wildcard matched")); 679fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan found_one = 1; 689fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_string = strdup(cap_text); 699fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan break; 709fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 719fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 729fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (strcmp(user, line) == 0) { 739fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("exact match for user")); 749fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan found_one = 1; 759fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_string = strdup(cap_text); 769fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan break; 779fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 789fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 799fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("user is not [%s] - skipping", line)); 809fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 819fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 829fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_text = NULL; 839fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan line = NULL; 849fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 859fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (found_one) { 869fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("user [%s] matched - caps are [%s]", user, cap_string)); 879fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan break; 889fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 899fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 909fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 919fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan fclose(cap_file); 929fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 939fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(buffer, 0, CAP_FILE_BUFFER_SIZE); 949fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 959fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return cap_string; 969fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan} 979fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 989fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan/* 999fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * Set capabilities for current process to match the current 1009fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * permitted+executable sets combined with the configured inheritable 1019fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * set. 1029fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan */ 1039fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1049fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganstatic int set_capabilities(struct pam_cap_s *cs) 1059fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan{ 1069fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_t cap_s; 1079fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan ssize_t length = 0; 1089fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char *conf_icaps; 1099fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char *proc_epcaps; 1109fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char *combined_caps; 1119fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int ok = 0; 1129fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1139fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_s = cap_get_proc(); 1149fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (cap_s == NULL) { 1159fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("your kernel is capability challenged - upgrade: %s", 1169fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan strerror(errno))); 1179fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return 0; 1189fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1199fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1209fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan conf_icaps = 1219fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan read_capabilities_for_user(cs->user, 1229fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cs->conf_filename 1239fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan ? cs->conf_filename:USER_CAP_FILE ); 1249fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (conf_icaps == NULL) { 1259fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("no capabilities found for user [%s]", cs->user)); 1269fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan goto cleanup_cap_s; 1279fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1289fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1299fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan proc_epcaps = cap_to_text(cap_s, &length); 1309fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (proc_epcaps == NULL) { 1319fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("unable to convert process capabilities to text")); 1329fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan goto cleanup_icaps; 1339fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1349fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1359fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan /* 1369fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * This is a pretty inefficient way to combine 1379fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * capabilities. However, it seems to be the most straightforward 1389fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * one, given the limitations of the POSIX.1e draft spec. The spec 1399fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * is optimized for applications that know the capabilities they 1409fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan * want to manipulate at compile time. 1419fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan */ 1429fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1439fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan combined_caps = malloc(1+strlen(CAP_COMBINED_FORMAT) 1449fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan +strlen(proc_epcaps)+strlen(conf_icaps)); 1459fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (combined_caps == NULL) { 1469fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("unable to combine capabilities into one string - no memory")); 1479fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan goto cleanup_epcaps; 1489fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1499fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1509fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (!strcmp(conf_icaps, "none")) { 1519fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan sprintf(combined_caps, CAP_DROP_ALL, proc_epcaps); 1529fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } else if (!strcmp(conf_icaps, "all")) { 1539fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan /* no change */ 1549fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan sprintf(combined_caps, "%s", proc_epcaps); 1559fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } else { 1569fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan sprintf(combined_caps, CAP_COMBINED_FORMAT, proc_epcaps, conf_icaps); 1579fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1589fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("combined_caps=[%s]", combined_caps)); 1599fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1609fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_free(cap_s); 1619fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_s = cap_from_text(combined_caps); 1629fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_overwrite(combined_caps); 1639fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_drop(combined_caps); 1649fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1659fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#ifdef DEBUG 1669fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan { 1679fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char *temp = cap_to_text(cap_s, NULL); 1689fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("abbreviated caps for process will be [%s]", temp)); 1699fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_free(temp); 1709fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1719fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan#endif /* DEBUG */ 1729fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1739fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (cap_s == NULL) { 1749fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("no capabilies to set")); 1759fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } else if (cap_set_proc(cap_s) == 0) { 1769fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("capabilities were set correctly")); 1779fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan ok = 1; 1789fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } else { 1799fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("failed to set specified capabilities: %s", strerror(errno))); 1809fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 1819fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1829fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgancleanup_epcaps: 1839fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_free(proc_epcaps); 1849fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1859fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgancleanup_icaps: 1869fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_overwrite(conf_icaps); 1879fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_drop(conf_icaps); 1889fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1899fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgancleanup_cap_s: 1909fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (cap_s) { 1919fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_free(cap_s); 1929fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan cap_s = NULL; 1939fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 194aadd6fad3f09bd5abcaacf8618fb8093a5aa7ba8Andrew Morgan 1959fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return ok; 1969fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan} 1979fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 1989fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan/* log errors */ 1999fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2009fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganstatic void _pam_log(int err, const char *format, ...) 2019fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan{ 2029fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan va_list args; 2039fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2049fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan va_start(args, format); 2059fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan openlog("pam_cap", LOG_CONS|LOG_PID, LOG_AUTH); 2069fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan vsyslog(err, format, args); 2079fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan va_end(args); 2089fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan closelog(); 2099fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan} 2109fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2119fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganstatic void parse_args(int argc, const char **argv, struct pam_cap_s *pcs) 2129fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan{ 2139fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int ctrl=0; 2149fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2159fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan /* step through arguments */ 2169fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan for (ctrl=0; argc-- > 0; ++argv) { 2179fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2189fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (!strcmp(*argv, "debug")) { 2199fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan pcs->debug = 1; 220627017564a647d46a5ec924b0484d22575956920Andrew G. Morgan } else if (!memcmp(*argv, "config=", 7)) { 221627017564a647d46a5ec924b0484d22575956920Andrew G. Morgan pcs->conf_filename = 7 + *argv; 2229fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } else { 2239fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_log(LOG_ERR, "unknown option; %s", *argv); 2249fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 2259fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2269fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 2279fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan} 2289fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2299fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganint pam_sm_authenticate(pam_handle_t *pamh, int flags, 2309fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int argc, const char **argv) 2319fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan{ 2329fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int retval; 2339fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan struct pam_cap_s pcs; 2349fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan char *conf_icaps; 2359fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2369fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(&pcs, 0, sizeof(pcs)); 2379fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2389fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan parse_args(argc, argv, &pcs); 2399fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2409fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan retval = pam_get_user(pamh, &pcs.user, NULL); 2419fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2429fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (retval == PAM_CONV_AGAIN) { 2439fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("user conversation is not available yet")); 2449fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(&pcs, 0, sizeof(pcs)); 2459fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return PAM_INCOMPLETE; 2469fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 2479fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2489fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (retval != PAM_SUCCESS) { 2499fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("pam_get_user failed: %s", pam_strerror(pamh, retval))); 2509fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(&pcs, 0, sizeof(pcs)); 2519fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return PAM_AUTH_ERR; 2529fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 2539fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2549fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan conf_icaps = 2559fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan read_capabilities_for_user(pcs.user, 2569fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan pcs.conf_filename 2579fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan ? pcs.conf_filename:USER_CAP_FILE ); 2589fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2599fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(&pcs, 0, sizeof(pcs)); 2609fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2619fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (conf_icaps) { 2629fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("it appears that there are capabilities for this user [%s]", 2639fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan conf_icaps)); 2649fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2659fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan /* We could also store this as a pam_[gs]et_data item for use 2669fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan by the setcred call to follow. As it is, there is a small 2679fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan race associated with a redundant read. Oh well, if you 2689fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan care, send me a patch.. */ 2699fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2709fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_overwrite(conf_icaps); 2719fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan _pam_drop(conf_icaps); 2729fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2739fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return PAM_SUCCESS; 2749fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2759fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } else { 2769fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2779fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("there are no capabilities restrctions on this user")); 2789fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return PAM_IGNORE; 2799fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2809fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 2819fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan} 2829fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2839fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morganint pam_sm_setcred(pam_handle_t *pamh, int flags, 2849fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int argc, const char **argv) 2859fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan{ 2869fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan int retval; 2879fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan struct pam_cap_s pcs; 2889fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2899fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if (!(flags & PAM_ESTABLISH_CRED)) { 2909fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("we don't handle much in the way of credentials")); 2919fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return PAM_IGNORE; 2929fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 2939fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2949fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(&pcs, 0, sizeof(pcs)); 2959fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2969fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan parse_args(argc, argv, &pcs); 2979fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 2989fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan retval = pam_get_item(pamh, PAM_USER, (const void **)&pcs.user); 2999fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan if ((retval != PAM_SUCCESS) || (pcs.user == NULL) || !(pcs.user[0])) { 3009fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 3019fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan D(("user's name is not set")); 3029fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return PAM_AUTH_ERR; 3039fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan } 3049fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 3059fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan retval = set_capabilities(&pcs); 3069fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 3079fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan memset(&pcs, 0, sizeof(pcs)); 3089fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan 3099fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan return (retval ? PAM_SUCCESS:PAM_IGNORE ); 3109fe5d0568f1e1a2c103a3293db87be075f8c1558Andrew Morgan} 311