/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * First known version of this code published internally at Sun in 1999. * It later appeared on SunSolve as part of an InfoDoc */ /* * pam_netgroup.c - restrict acces based on username or netgroup * Used to overcome the perfomance problems of using * passwd_compat in nsswitch.conf * * Compile: * * cc pam_netgroup.c -o pam_netgroup.so.1 -Kpic -G * * Install: * * cp pam_netgroup.so.1 /usr/local/lib * chmod 755 /usr/local/lib/pam_netgroup.so.1 * * update /etc/pam.conf with something like this * * other account requisite pam_roles.so.1 * other account required pam_unix_account.so.1 * other account required pam_netgroup.so.1 * */ #include #include #include #include #include #include #include #include #include #define ALLOW_FILE "/etc/users.allow" #define debug fprintf int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv) { FILE *allowfl; char buf[BUFSIZ]; char *username = NULL; int buflen = 0; char *netgroup; char *rhost; struct stat allowfl_stat; int check_user = 1; int check_host = 0; int check_exact = 0; int userok = 0; int hostok = 0; int i, j; for (i = 0; i < argc; ++i) { if (strcasecmp(argv[i], "user") == 0) { check_user = 1; } else if (strcasecmp(argv[i], "nouser") == 0) { check_user = 0; } else if (strcasecmp(argv[i], "host") == 0) { check_host = 1; } else if (strcasecmp(argv[i], "exact") == 0) { check_exact = 1; } else { syslog(LOG_ERR, "PAM_NETGROUP pam_sm_acct_mgmt: " "illegal option %s", argv[i]); return (PAM_SERVICE_ERR); } } debug(stderr, "check_user = %d, check_host = %d, check_exact = %d\n", check_user, check_host, check_exact); if (lstat(ALLOW_FILE, &allowfl_stat) < 0) { syslog(LOG_ERR, "PAM_NETGROUP pam_sm_acct_mgmt: " "lstat of %s failed", ALLOW_FILE); return (PAM_SERVICE_ERR); } if (S_ISREG(allowfl_stat.st_mode) && /* no symbolic links */ (allowfl_stat.st_nlink > 1) && /* no hard links */ (allowfl_stat.st_uid == 0)) { /* owned by root */ syslog(LOG_ERR, "PAM_NETGROUP pam_sm_acct_mgmt: " "%s is/has links or isn't owned by root\n", ALLOW_FILE); return (PAM_SERVICE_ERR); } if ((allowfl = fopen(ALLOW_FILE, "r")) == NULL) { return (PAM_SERVICE_ERR); } if (pam_get_item(pamh, PAM_USER, (void**)&username) != PAM_SUCCESS) { return (PAM_SERVICE_ERR); } pam_get_item(pamh, PAM_RHOST, (void**)&rhost); if (rhost != NULL) debug(stderr, "pam_netgroup:pam_sm_acct_mgt for (%s,%s,)\n", rhost, username); else debug(stderr, "pam_netgroup:pam_sm_acct_mgt for (,%s,)\n", username); while (fgets(buf, BUFSIZ-1, allowfl) != NULL) { buflen = strlen(buf); if (buflen > 1) { buf[buflen - 1] = '\0'; buflen -= 1; } else { return (PAM_SERVICE_ERR); } if (buf[0] == '#') continue; if ((buf[0] == '@') && (buf[1] != '\0')) { if ((netgroup = (char *)malloc(buflen)) == NULL) { perror("pam_netgroup: malloc"); return (PAM_SERVICE_ERR); } for (i = 1, j = 0; i < buflen; ++i, ++j) { netgroup[j] = buf[i]; } netgroup[j] = '\0'; debug(stderr, "Checking netgroup: %s\n", netgroup); if (check_exact) { if (innetgr(netgroup, rhost, username, NULL) == 1) { debug(stderr, "Found in netgroup %s\n", netgroup); return (PAM_SUCCESS); } } else { userok = hostok = 0; if (check_user) { userok = innetgr(netgroup, NULL, username, NULL) == 1; } else { userok = 1; } if (check_host) { hostok = innetgr(netgroup, rhost, NULL, NULL); } else { hostok = 1; } if (userok && hostok) { debug(stderr, "Found user & host\n"); return (PAM_SUCCESS); } } } else { debug(stderr, "Checking user: %s\n", buf); if (strcmp(buf, username) == 0) { debug(stderr, "Found user %s\n", buf); return (PAM_SUCCESS); } } } return (PAM_AUTH_ERR); }