pam_ssh.c (89753) | pam_ssh.c (89760) |
---|---|
1/*- 2 * Copyright (c) 1999, 2000 Andrew J. Korty 3 * All rights reserved. 4 * Copyright (c) 2001 Networks Associates Technologies, Inc. 5 * All rights reserved. 6 * 7 * Portions of this software were developed for the FreeBSD Project by 8 * ThinkSec AS and NAI Labs, the Security Research Division of Network --- 21 unchanged lines hidden (view full) --- 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1999, 2000 Andrew J. Korty 3 * All rights reserved. 4 * Copyright (c) 2001 Networks Associates Technologies, Inc. 5 * All rights reserved. 6 * 7 * Portions of this software were developed for the FreeBSD Project by 8 * ThinkSec AS and NAI Labs, the Security Research Division of Network --- 21 unchanged lines hidden (view full) --- 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37#include <sys/cdefs.h> |
38__FBSDID("$FreeBSD: head/lib/libpam/modules/pam_ssh/pam_ssh.c 89753 2002-01-24 17:26:27Z des $"); | 38__FBSDID("$FreeBSD: head/lib/libpam/modules/pam_ssh/pam_ssh.c 89760 2002-01-24 18:37:17Z markm $"); |
39 40#include <sys/param.h> 41#include <sys/socket.h> 42#include <sys/stat.h> 43#include <sys/wait.h> 44 45#include <dirent.h> 46#include <pwd.h> --- 16 unchanged lines hidden (view full) --- 63#include <openssl/evp.h> 64 65#include "key.h" 66#include "authfd.h" 67#include "authfile.h" 68#include "log.h" 69#include "pam_ssh.h" 70 | 39 40#include <sys/param.h> 41#include <sys/socket.h> 42#include <sys/stat.h> 43#include <sys/wait.h> 44 45#include <dirent.h> 46#include <pwd.h> --- 16 unchanged lines hidden (view full) --- 63#include <openssl/evp.h> 64 65#include "key.h" 66#include "authfd.h" 67#include "authfile.h" 68#include "log.h" 69#include "pam_ssh.h" 70 |
71static int auth_via_key(pam_handle_t *, int, const char *, const char *, const struct passwd *, const char *); 72static void key_cleanup(pam_handle_t *, void *, int); 73static void ssh_cleanup(pam_handle_t *, void *, int); 74 |
|
71/* 72 * Generic cleanup function for SSH "Key" type. 73 */ 74 | 75/* 76 * Generic cleanup function for SSH "Key" type. 77 */ 78 |
75void 76key_cleanup(pam_handle_t *pamh, void *data, int error_status) | 79static void 80key_cleanup(pam_handle_t *pamh __unused, void *data, int error_status __unused) |
77{ 78 if (data) 79 key_free(data); 80} 81 82 83/* 84 * Generic PAM cleanup function for this module. 85 */ 86 | 81{ 82 if (data) 83 key_free(data); 84} 85 86 87/* 88 * Generic PAM cleanup function for this module. 89 */ 90 |
87void 88ssh_cleanup(pam_handle_t *pamh, void *data, int error_status) | 91static void 92ssh_cleanup(pam_handle_t *pamh __unused, void *data, int error_status __unused) |
89{ 90 if (data) 91 free(data); 92} 93 94 95/* 96 * Authenticate a user's key by trying to decrypt it with the password 97 * provided. The key and its comment are then stored for later 98 * retrieval by the session phase. An increasing index is embedded in 99 * the PAM variable names so this function may be called multiple times 100 * for multiple keys. 101 */ 102 | 93{ 94 if (data) 95 free(data); 96} 97 98 99/* 100 * Authenticate a user's key by trying to decrypt it with the password 101 * provided. The key and its comment are then stored for later 102 * retrieval by the session phase. An increasing index is embedded in 103 * the PAM variable names so this function may be called multiple times 104 * for multiple keys. 105 */ 106 |
103int | 107static int |
104auth_via_key(pam_handle_t *pamh, int type, const char *file, 105 const char *dir, const struct passwd *user, const char *pass) 106{ 107 char *comment; /* private key comment */ 108 char *data_name; /* PAM state */ | 108auth_via_key(pam_handle_t *pamh, int type, const char *file, 109 const char *dir, const struct passwd *user, const char *pass) 110{ 111 char *comment; /* private key comment */ 112 char *data_name; /* PAM state */ |
109 static int index = 0; /* for saved keys */ | 113 static int indx = 0; /* for saved keys */ |
110 Key *key; /* user's key */ 111 char *path; /* to key files */ 112 int retval; /* from calls */ 113 uid_t saved_uid; /* caller's uid */ 114 115 /* locate the user's private key file */ 116 if (!asprintf(&path, "%s/%s", dir, file)) { 117 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); --- 9 unchanged lines hidden (view full) --- 127 free(path); 128 seteuid(saved_uid); 129 if (key == NULL) 130 return PAM_AUTH_ERR; 131 /* 132 * Save the key and comment to pass to ssh-agent in the session 133 * phase. 134 */ | 114 Key *key; /* user's key */ 115 char *path; /* to key files */ 116 int retval; /* from calls */ 117 uid_t saved_uid; /* caller's uid */ 118 119 /* locate the user's private key file */ 120 if (!asprintf(&path, "%s/%s", dir, file)) { 121 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); --- 9 unchanged lines hidden (view full) --- 131 free(path); 132 seteuid(saved_uid); 133 if (key == NULL) 134 return PAM_AUTH_ERR; 135 /* 136 * Save the key and comment to pass to ssh-agent in the session 137 * phase. 138 */ |
135 if (!asprintf(&data_name, "ssh_private_key_%d", index)) { | 139 if (!asprintf(&data_name, "ssh_private_key_%d", indx)) { |
136 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 137 free(comment); 138 return PAM_SERVICE_ERR; 139 } 140 retval = pam_set_data(pamh, data_name, key, key_cleanup); 141 free(data_name); 142 if (retval != PAM_SUCCESS) { 143 key_free(key); 144 free(comment); 145 return retval; 146 } | 140 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 141 free(comment); 142 return PAM_SERVICE_ERR; 143 } 144 retval = pam_set_data(pamh, data_name, key, key_cleanup); 145 free(data_name); 146 if (retval != PAM_SUCCESS) { 147 key_free(key); 148 free(comment); 149 return retval; 150 } |
147 if (!asprintf(&data_name, "ssh_key_comment_%d", index)) { | 151 if (!asprintf(&data_name, "ssh_key_comment_%d", indx)) { |
148 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 149 free(comment); 150 return PAM_SERVICE_ERR; 151 } 152 retval = pam_set_data(pamh, data_name, comment, ssh_cleanup); 153 free(data_name); 154 if (retval != PAM_SUCCESS) { 155 free(comment); 156 return retval; 157 } | 152 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 153 free(comment); 154 return PAM_SERVICE_ERR; 155 } 156 retval = pam_set_data(pamh, data_name, comment, ssh_cleanup); 157 free(data_name); 158 if (retval != PAM_SUCCESS) { 159 free(comment); 160 return retval; 161 } |
158 ++index; | 162 ++indx; |
159 return PAM_SUCCESS; 160} 161 162 163PAM_EXTERN int | 163 return PAM_SUCCESS; 164} 165 166 167PAM_EXTERN int |
164pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) | 168pam_sm_authenticate(pam_handle_t *pamh, int flags __unused, int argc, const char **argv) |
165{ 166 struct options options; /* module options */ 167 int authenticated; /* user authenticated? */ 168 char *dotdir; /* .ssh2 dir name */ 169 struct dirent *dotdir_ent; /* .ssh2 dir entry */ 170 DIR *dotdir_p; /* .ssh2 dir pointer */ 171 const char *pass; /* passphrase */ 172 struct passwd *pwd; /* user's passwd entry */ --- 106 unchanged lines hidden (view full) --- 279 280 PAM_LOG("Saved ssh_passwd_entry"); 281 282 PAM_RETURN(PAM_SUCCESS); 283} 284 285 286PAM_EXTERN int | 169{ 170 struct options options; /* module options */ 171 int authenticated; /* user authenticated? */ 172 char *dotdir; /* .ssh2 dir name */ 173 struct dirent *dotdir_ent; /* .ssh2 dir entry */ 174 DIR *dotdir_p; /* .ssh2 dir pointer */ 175 const char *pass; /* passphrase */ 176 struct passwd *pwd; /* user's passwd entry */ --- 106 unchanged lines hidden (view full) --- 283 284 PAM_LOG("Saved ssh_passwd_entry"); 285 286 PAM_RETURN(PAM_SUCCESS); 287} 288 289 290PAM_EXTERN int |
287pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv) | 291pam_sm_setcred(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv) |
288{ 289 struct options options; /* module options */ 290 291 pam_std_option(&options, NULL, argc, argv); 292 293 PAM_LOG("Options processed"); 294 295 PAM_RETURN(PAM_SUCCESS); 296} 297 298PAM_EXTERN int | 292{ 293 struct options options; /* module options */ 294 295 pam_std_option(&options, NULL, argc, argv); 296 297 PAM_LOG("Options processed"); 298 299 PAM_RETURN(PAM_SUCCESS); 300} 301 302PAM_EXTERN int |
299pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc ,const char **argv) | 303pam_sm_acct_mgmt(pam_handle_t *pamh __unused, int flags __unused, int argc ,const char **argv) |
300{ 301 struct options options; 302 303 pam_std_option(&options, NULL, argc, argv); 304 305 PAM_LOG("Options processed"); 306 307 PAM_RETURN(PAM_IGNORE); 308} 309 310PAM_EXTERN int | 304{ 305 struct options options; 306 307 pam_std_option(&options, NULL, argc, argv); 308 309 PAM_LOG("Options processed"); 310 311 PAM_RETURN(PAM_IGNORE); 312} 313 314PAM_EXTERN int |
311pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv) | 315pam_sm_chauthtok(pam_handle_t *pamh __unused, int flags __unused, int argc, const char **argv) |
312{ 313 struct options options; 314 315 pam_std_option(&options, NULL, argc, argv); 316 317 PAM_LOG("Options processed"); 318 319 PAM_RETURN(PAM_IGNORE); 320} 321 322typedef AuthenticationConnection AC; 323 324PAM_EXTERN int | 316{ 317 struct options options; 318 319 pam_std_option(&options, NULL, argc, argv); 320 321 PAM_LOG("Options processed"); 322 323 PAM_RETURN(PAM_IGNORE); 324} 325 326typedef AuthenticationConnection AC; 327 328PAM_EXTERN int |
325pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv) | 329pam_sm_open_session(pam_handle_t *pamh, int flags __unused, int argc, const char **argv) |
326{ 327 struct options options; /* module options */ 328 AC *ac; /* to ssh-agent */ 329 char *agent_socket; /* agent socket */ 330 char *comment; /* on private key */ 331 char *env_end; /* end of env */ 332 char *env_file; /* to store env */ 333 FILE *env_fp; /* env_file handle */ 334 char *env_value; /* envariable value */ 335 char *data_name; /* PAM state */ 336 int final; /* final return value */ | 330{ 331 struct options options; /* module options */ 332 AC *ac; /* to ssh-agent */ 333 char *agent_socket; /* agent socket */ 334 char *comment; /* on private key */ 335 char *env_end; /* end of env */ 336 char *env_file; /* to store env */ 337 FILE *env_fp; /* env_file handle */ 338 char *env_value; /* envariable value */ 339 char *data_name; /* PAM state */ 340 int final; /* final return value */ |
337 int index; /* for saved keys */ | 341 int indx; /* for saved keys */ |
338 Key *key; /* user's private key */ | 342 Key *key; /* user's private key */ |
339 FILE *pipe; /* ssh-agent handle */ | 343 FILE *lpipe; /* ssh-agent handle */ |
340 struct passwd *pwd; /* user's passwd entry */ 341 int retval; /* from calls */ 342 uid_t saved_uid; /* caller's uid */ 343 const char *tty; /* tty or display name */ 344 char hname[MAXHOSTNAMELEN]; /* local hostname */ 345 char env_string[BUFSIZ]; /* environment string */ 346 347 pam_std_option(&options, NULL, argc, argv); --- 40 unchanged lines hidden (view full) --- 388 PAM_LOG("Saved env_file"); 389 390 /* start the agent as the user */ 391 saved_uid = geteuid(); 392 seteuid(pwd->pw_uid); 393 env_fp = fopen(env_file, "w"); 394 if (env_fp != NULL) 395 chmod(env_file, S_IRUSR); | 344 struct passwd *pwd; /* user's passwd entry */ 345 int retval; /* from calls */ 346 uid_t saved_uid; /* caller's uid */ 347 const char *tty; /* tty or display name */ 348 char hname[MAXHOSTNAMELEN]; /* local hostname */ 349 char env_string[BUFSIZ]; /* environment string */ 350 351 pam_std_option(&options, NULL, argc, argv); --- 40 unchanged lines hidden (view full) --- 392 PAM_LOG("Saved env_file"); 393 394 /* start the agent as the user */ 395 saved_uid = geteuid(); 396 seteuid(pwd->pw_uid); 397 env_fp = fopen(env_file, "w"); 398 if (env_fp != NULL) 399 chmod(env_file, S_IRUSR); |
396 pipe = popen(SSH_AGENT, "r"); | 400 lpipe = popen(SSH_AGENT, "r"); |
397 seteuid(saved_uid); | 401 seteuid(saved_uid); |
398 if (!pipe) { | 402 if (!lpipe) { |
399 syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, SSH_AGENT); 400 if (env_fp) 401 fclose(env_fp); 402 PAM_RETURN(PAM_SESSION_ERR); 403 } 404 405 PAM_LOG("Agent started as user"); 406 407 /* 408 * Save environment for application with pam_putenv(). 409 */ 410 agent_socket = NULL; | 403 syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, SSH_AGENT); 404 if (env_fp) 405 fclose(env_fp); 406 PAM_RETURN(PAM_SESSION_ERR); 407 } 408 409 PAM_LOG("Agent started as user"); 410 411 /* 412 * Save environment for application with pam_putenv(). 413 */ 414 agent_socket = NULL; |
411 while (fgets(env_string, sizeof env_string, pipe)) { | 415 while (fgets(env_string, sizeof env_string, lpipe)) { |
412 if (env_fp) 413 fputs(env_string, env_fp); 414 env_value = strchr(env_string, '='); 415 if (env_value == NULL) 416 continue; 417 env_end = strchr(env_value, ';'); 418 if (env_end == NULL) 419 continue; 420 *env_end = '\0'; 421 /* pass to the application ... */ 422 retval = pam_putenv(pamh, env_string); 423 if (retval != PAM_SUCCESS) { | 416 if (env_fp) 417 fputs(env_string, env_fp); 418 env_value = strchr(env_string, '='); 419 if (env_value == NULL) 420 continue; 421 env_end = strchr(env_value, ';'); 422 if (env_end == NULL) 423 continue; 424 *env_end = '\0'; 425 /* pass to the application ... */ 426 retval = pam_putenv(pamh, env_string); 427 if (retval != PAM_SUCCESS) { |
424 pclose(pipe); | 428 pclose(lpipe); |
425 if (env_fp) 426 fclose(env_fp); 427 PAM_RETURN(PAM_SERVICE_ERR); 428 } 429 430 PAM_LOG("Put to environment: %s", env_string); 431 432 *env_value++ = '\0'; --- 16 unchanged lines hidden (view full) --- 449 env_value, ssh_cleanup); 450 if (retval != PAM_SUCCESS) 451 PAM_RETURN(retval); 452 PAM_LOG("Environment write successful"); 453 } 454 } 455 if (env_fp) 456 fclose(env_fp); | 429 if (env_fp) 430 fclose(env_fp); 431 PAM_RETURN(PAM_SERVICE_ERR); 432 } 433 434 PAM_LOG("Put to environment: %s", env_string); 435 436 *env_value++ = '\0'; --- 16 unchanged lines hidden (view full) --- 453 env_value, ssh_cleanup); 454 if (retval != PAM_SUCCESS) 455 PAM_RETURN(retval); 456 PAM_LOG("Environment write successful"); 457 } 458 } 459 if (env_fp) 460 fclose(env_fp); |
457 retval = pclose(pipe); | 461 retval = pclose(lpipe); |
458 switch (retval) { 459 case -1: 460 syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, SSH_AGENT); 461 PAM_RETURN(PAM_SESSION_ERR); 462 case 0: 463 break; 464 case 127: 465 syslog(LOG_ERR, "%s: cannot execute %s", MODULE_NAME, --- 17 unchanged lines hidden (view full) --- 483 syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, agent_socket); 484 PAM_RETURN(PAM_SESSION_ERR); 485 } 486 487 PAM_LOG("Connected to agent"); 488 489 /* hand off each private key to the agent */ 490 final = 0; | 462 switch (retval) { 463 case -1: 464 syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, SSH_AGENT); 465 PAM_RETURN(PAM_SESSION_ERR); 466 case 0: 467 break; 468 case 127: 469 syslog(LOG_ERR, "%s: cannot execute %s", MODULE_NAME, --- 17 unchanged lines hidden (view full) --- 487 syslog(LOG_ERR, "%s: %s: %m", MODULE_NAME, agent_socket); 488 PAM_RETURN(PAM_SESSION_ERR); 489 } 490 491 PAM_LOG("Connected to agent"); 492 493 /* hand off each private key to the agent */ 494 final = 0; |
491 for (index = 0; ; index++) { 492 if (!asprintf(&data_name, "ssh_private_key_%d", index)) { | 495 for (indx = 0; ; indx++) { 496 if (!asprintf(&data_name, "ssh_private_key_%d", indx)) { |
493 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 494 ssh_close_authentication_connection(ac); 495 PAM_RETURN(PAM_SERVICE_ERR); 496 } 497 retval = pam_get_data(pamh, data_name, (const void **)&key); 498 free(data_name); 499 if (retval != PAM_SUCCESS) 500 break; | 497 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 498 ssh_close_authentication_connection(ac); 499 PAM_RETURN(PAM_SERVICE_ERR); 500 } 501 retval = pam_get_data(pamh, data_name, (const void **)&key); 502 free(data_name); 503 if (retval != PAM_SUCCESS) 504 break; |
501 if (!asprintf(&data_name, "ssh_key_comment_%d", index)) { | 505 if (!asprintf(&data_name, "ssh_key_comment_%d", indx)) { |
502 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 503 ssh_close_authentication_connection(ac); 504 PAM_RETURN(PAM_SERVICE_ERR); 505 } 506 retval = pam_get_data(pamh, data_name, (const void **)&comment); 507 free(data_name); 508 if (retval != PAM_SUCCESS) 509 break; --- 5 unchanged lines hidden (view full) --- 515 516 PAM_LOG("Keys handed off"); 517 518 PAM_RETURN(final ? PAM_SUCCESS : PAM_SESSION_ERR); 519} 520 521 522PAM_EXTERN int | 506 syslog(LOG_CRIT, "%s: %m", MODULE_NAME); 507 ssh_close_authentication_connection(ac); 508 PAM_RETURN(PAM_SERVICE_ERR); 509 } 510 retval = pam_get_data(pamh, data_name, (const void **)&comment); 511 free(data_name); 512 if (retval != PAM_SUCCESS) 513 break; --- 5 unchanged lines hidden (view full) --- 519 520 PAM_LOG("Keys handed off"); 521 522 PAM_RETURN(final ? PAM_SUCCESS : PAM_SESSION_ERR); 523} 524 525 526PAM_EXTERN int |
523pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, const char **argv) | 527pam_sm_close_session(pam_handle_t *pamh, int flags __unused, int argc, const char **argv) |
524{ 525 struct options options; /* module options */ 526 const char *env_file; /* ssh-agent environment */ 527 pid_t pid; /* ssh-agent process id */ 528 int retval; /* from calls */ 529 const char *ssh_agent_pid; /* ssh-agent pid string */ 530 531 pam_std_option(&options, NULL, argc, argv); --- 36 unchanged lines hidden --- | 528{ 529 struct options options; /* module options */ 530 const char *env_file; /* ssh-agent environment */ 531 pid_t pid; /* ssh-agent process id */ 532 int retval; /* from calls */ 533 const char *ssh_agent_pid; /* ssh-agent pid string */ 534 535 pam_std_option(&options, NULL, argc, argv); --- 36 unchanged lines hidden --- |