su.c (97241) | su.c (99158) |
---|---|
1/*- 2 * Copyright (c) 2002 Networks Associates Technology, Inc. 3 * All rights reserved. 4 * 5 * This software was developed for the FreeBSD Project by ThinkSec AS and | 1/*- 2 * Copyright (c) 2002 Networks Associates Technology, Inc. 3 * All rights reserved. 4 * 5 * This software was developed for the FreeBSD Project by ThinkSec AS and |
6 * NAI Labs, the Security Research Division of Network Associates, Inc. 7 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 8 * DARPA CHATS research program. | 6 * Network Associates Laboratories, the Security Research Division of 7 * Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 8 * ("CBOSS"), as part of the DARPA CHATS research program. |
9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the --- 9 unchanged lines hidden (view full) --- 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * | 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the --- 9 unchanged lines hidden (view full) --- 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * |
34 * $P4: //depot/projects/openpam/bin/su/su.c#6 $ | 34 * $P4: //depot/projects/openpam/bin/su/su.c#8 $ |
35 */ 36 37#include <sys/param.h> 38#include <sys/wait.h> 39 40#include <err.h> 41#include <pwd.h> 42#include <stdio.h> 43#include <stdlib.h> | 35 */ 36 37#include <sys/param.h> 38#include <sys/wait.h> 39 40#include <err.h> 41#include <pwd.h> 42#include <stdio.h> 43#include <stdlib.h> |
44#include <string.h> |
|
44#include <syslog.h> 45#include <unistd.h> 46 47#include <security/pam_appl.h> | 45#include <syslog.h> 46#include <unistd.h> 47 48#include <security/pam_appl.h> |
48#include | 49#include <security/openpam.h> /* for openpam_ttyconv() */ |
49 | 50 |
51extern char **environ; 52 |
|
50static pam_handle_t *pamh; 51static struct pam_conv pamc; 52 53static void 54usage(void) 55{ 56 57 fprintf(stderr, "Usage: su [login [args]]\n"); 58 exit(1); 59} 60 | 53static pam_handle_t *pamh; 54static struct pam_conv pamc; 55 56static void 57usage(void) 58{ 59 60 fprintf(stderr, "Usage: su [login [args]]\n"); 61 exit(1); 62} 63 |
61static int 62check(const char *func, int pam_err) 63{ 64 65 if (pam_err == PAM_SUCCESS || pam_err == PAM_NEW_AUTHTOK_REQD) 66 return pam_err; 67 openlog("su", LOG_CONS, LOG_AUTH); 68 syslog(LOG_ERR, "%s(): %s", func, pam_strerror(pamh, pam_err)); 69 errx(1, "Sorry."); 70} 71 | |
72int 73main(int argc, char *argv[]) 74{ 75 char hostname[MAXHOSTNAMELEN]; 76 const char *user, *tty; | 64int 65main(int argc, char *argv[]) 66{ 67 char hostname[MAXHOSTNAMELEN]; 68 const char *user, *tty; |
69 char **args, **pam_envlist, **pam_env; |
|
77 struct passwd *pwd; | 70 struct passwd *pwd; |
78 int o, status; | 71 int o, pam_err, status; |
79 pid_t pid; 80 81 while ((o = getopt(argc, argv, "h")) != -1) 82 switch (o) { 83 case 'h': 84 default: 85 usage(); 86 } 87 88 argc -= optind; 89 argv += optind; 90 91 /* initialize PAM */ 92 pamc.conv = &openpam_ttyconv; 93 pam_start("su", argc ? *argv : "root", &pamc, &pamh); 94 95 /* set some items */ 96 gethostname(hostname, sizeof(hostname)); | 72 pid_t pid; 73 74 while ((o = getopt(argc, argv, "h")) != -1) 75 switch (o) { 76 case 'h': 77 default: 78 usage(); 79 } 80 81 argc -= optind; 82 argv += optind; 83 84 /* initialize PAM */ 85 pamc.conv = &openpam_ttyconv; 86 pam_start("su", argc ? *argv : "root", &pamc, &pamh); 87 88 /* set some items */ 89 gethostname(hostname, sizeof(hostname)); |
97 check("pam_set_item", pam_set_item(pamh, PAM_RHOST, hostname)); | 90 if ((pam_err = pam_set_item(pamh, PAM_RHOST, hostname)) != PAM_SUCCESS) 91 goto pamerr; |
98 user = getlogin(); | 92 user = getlogin(); |
99 check("pam_set_item", pam_set_item(pamh, PAM_RUSER, user)); | 93 if ((pam_err = pam_set_item(pamh, PAM_RUSER, user)) != PAM_SUCCESS) 94 goto pamerr; |
100 tty = ttyname(STDERR_FILENO); | 95 tty = ttyname(STDERR_FILENO); |
101 check("pam_set_item", pam_set_item(pamh, PAM_TTY, tty)); | 96 if ((pam_err = pam_set_item(pamh, PAM_TTY, tty)) != PAM_SUCCESS) 97 goto pamerr; |
102 103 /* authenticate the applicant */ | 98 99 /* authenticate the applicant */ |
104 check("pam_authenticate", pam_authenticate(pamh, 0)); 105 if (check("pam_acct_mgmt", pam_acct_mgmt(pamh, 0)) == 106 PAM_NEW_AUTHTOK_REQD) 107 check("pam_chauthtok", 108 pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK)); | 100 if ((pam_err = pam_authenticate(pamh, 0)) != PAM_SUCCESS) 101 goto pamerr; 102 if ((pam_err = pam_acct_mgmt(pamh, 0)) == PAM_NEW_AUTHTOK_REQD) 103 pam_err = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK); 104 if (pam_err != PAM_SUCCESS) 105 goto pamerr; |
109 110 /* establish the requested credentials */ | 106 107 /* establish the requested credentials */ |
111 check("pam_setcred", pam_setcred(pamh, PAM_ESTABLISH_CRED)); | 108 if ((pam_err = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) 109 goto pamerr; |
112 113 /* authentication succeeded; open a session */ | 110 111 /* authentication succeeded; open a session */ |
114 check("pam_open_session", pam_open_session(pamh, 0)); | 112 if ((pam_err = pam_open_session(pamh, 0)) != PAM_SUCCESS) 113 goto pamerr; |
115 | 114 |
116 if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) 117 err(1, "initgroups()"); 118 if (setuid(pwd->pw_uid) == -1) 119 err(1, "setuid()"); | 115 /* get mapped user name; PAM may have changed it */ 116 pam_err = pam_get_item(pamh, PAM_USER, (const void **)&user); 117 if (pam_err != PAM_SUCCESS || (pwd = getpwnam(user)) == NULL) 118 goto pamerr; |
120 | 119 |
121 /* XXX export environment variables */ | 120 /* set uid and groups */ 121 if (initgroups(pwd->pw_name, pwd->pw_gid) == -1) { 122 warn("initgroups()"); 123 goto err; 124 } 125 if (setgid(pwd->pw_gid) == -1) { 126 warn("setgid()"); 127 goto err; 128 } 129 if (setuid(pwd->pw_uid) == -1) { 130 warn("setuid()"); 131 goto err; 132 } |
122 | 133 |
134 /* export PAM environment */ 135 if ((pam_envlist = pam_getenvlist(pamh)) != NULL) { 136 for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env) { 137 putenv(*pam_env); 138 free(*pam_env); 139 } 140 free(pam_envlist); 141 } 142 143 /* build argument list */ 144 if ((args = calloc(argc + 2, sizeof *args)) == NULL) { 145 warn("calloc()"); 146 goto err; 147 } 148 *args = pwd->pw_shell; 149 memcpy(args + 1, argv, argc * sizeof *args); 150 151 /* fork and exec */ |
|
123 switch ((pid = fork())) { 124 case -1: | 152 switch ((pid = fork())) { 153 case -1: |
125 err(1, "fork()"); | 154 warn("fork()"); 155 goto err; |
126 case 0: 127 /* child: start a shell */ | 156 case 0: 157 /* child: start a shell */ |
128 *argv = pwd->pw_shell; 129 execvp(*argv, argv); 130 err(1, "execvp()"); | 158 execve(*args, args, environ); 159 warn("execve()"); 160 _exit(1); |
131 default: 132 /* parent: wait for child to exit */ 133 waitpid(pid, &status, 0); | 161 default: 162 /* parent: wait for child to exit */ 163 waitpid(pid, &status, 0); |
134 if (WIFEXITED(status)) 135 status = WEXITSTATUS(status); 136 else 137 status = 1; 138 } | |
139 | 164 |
140 /* close the session and release PAM resources */ 141 check("pam_close_session", pam_close_session(pamh, 0)); 142 check("pam_end", pam_end(pamh, 0)); | 165 /* close the session and release PAM resources */ 166 pam_err = pam_close_session(pamh, 0); 167 pam_end(pamh, pam_err); |
143 | 168 |
144 exit(status); | 169 exit(WEXITSTATUS(status)); 170 } 171 172pamerr: 173 pam_end(pamh, pam_err); 174 fprintf(stderr, "Sorry\n"); 175 exit(1); 176err: 177 pam_end(pamh, pam_err); 178 exit(1); |
145} | 179} |