The following are patches against openssh 2.1.1p4 to add support for the BSD_AUTH authentication mechanisms. It allows the use of non-challenge/response style mechanisms (which styles are allowed my be limited by appropriate auth-ssh entries in login.conf). The patches also add support for calling setusercontext for the appropriate class when called with a command (so that the PATH, limits, etc. are set appropriately for the class the user is part of). login -h takes care of this when ssh is called for a regular login. To have access to the class when setting up the session, I had to add preserving it in ssh.c, and both version 1 and version 2 auth routines. I made that conditional on the last CSRG release BSD/OS is based on (all of the other BSD's should also have it). Please let me know if you have different suggestions. It looks like the s/key challenge/response code is really a hack using the debugging messages for the challenge on the first login attempt. It looked pretty painful, so I didn't bother making generic challenge/response for BSD_AUTH work using that mechanism. Is there something I'm missing that would make challenge/response more reasonable? Jeff Index: auth1.c ==================================================================RCS file: /master/contrib/openssh/auth1.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 auth1.c *** auth1.c 2000/08/17 16:17:52 1.1.1.1 --- auth1.c 2000/10/06 20:45:57 *************** *** 23,28 **** --- 23,34 ---- # include <siad.h> #endif + #ifdef HAVE_BSD_AUTH + # include <login_cap.h> + # include <bsd_auth.h> + static char *bsduser=NULL; /* XXX -- ugly, but we need the original */ + #endif + /* import */ extern ServerOptions options; extern char *forced_command; *************** *** 315,321 **** NULL, password) == SIASUCCESS) { authenticated = 1; } ! #else /* !USE_PAM && !HAVE_OSF_SIA */ /* Try authentication with the password. */ authenticated = auth_password(pw, password); #endif /* USE_PAM */ --- 321,330 ---- NULL, password) == SIASUCCESS) { authenticated = 1; } ! #elif defined(HAVE_BSD_AUTH) ! authenticated = auth_userokay(bsduser, NULL, ! "auth-ssh", password); ! #else /* !USE_PAM && !HAVE_OSF_SIA && !HAVE_BSD_AUTH */ /* Try authentication with the password. */ authenticated = auth_password(pw, password); #endif /* USE_PAM */ *************** *** 469,474 **** --- 478,492 ---- #endif /* AFS */ /* Verify that the user is a valid user. */ + #ifdef HAVE_BSD_AUTH + /* we may have an auth type in the user name we need to strip */ + { + char *p; + bsduser = xstrdup(user); + if ((p = strchr(user, ':')) != NULL) + *p = '\0'; + } + #endif pw = getpwnam(user); if (!pw || !allowed_user(pw)) do_fake_authloop1(user); *************** *** 482,487 **** --- 500,508 ---- pwcopy.pw_gid = pw->pw_gid; pwcopy.pw_dir = xstrdup(pw->pw_dir); pwcopy.pw_shell = xstrdup(pw->pw_shell); + #if defined(BSD) && BSD >= 199506 + pwcopy.pw_class = xstrdup(pw->pw_class); + #endif pw = &pwcopy; #ifdef USE_PAM *************** *** 508,514 **** (sia_validate_user(NULL, saved_argc, saved_argv, get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, "") == SIASUCCESS)) { ! #else /* !HAVE_OSF_SIA && !USE_PAM */ auth_password(pw, "")) { #endif /* USE_PAM */ /* Authentication with empty password succeeded. */ --- 529,537 ---- (sia_validate_user(NULL, saved_argc, saved_argv, get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, "") == SIASUCCESS)) { ! #elif defined(HAVE_BSD_AUTH) ! auth_userokay(bsduser, NULL, "auth-ssh", "" )) { ! #else /* !HAVE_OSF_SIA && !USE_PAM && !HAVE_BSD_AUTH */ auth_password(pw, "")) { #endif /* USE_PAM */ /* Authentication with empty password succeeded. */ *************** *** 520,525 **** --- 543,555 ---- authentication is successfull */ do_authloop(pw); } + + #ifdef HAVE_BSD_AUTH + if (bsduser != NULL) { + xfree(bsduser); + bsduser = NULL; + } + #endif /* The user has been authenticated and accepted. */ #ifdef WITH_AIXAUTHENTICATE Index: auth2.c ==================================================================RCS file: /master/contrib/openssh/auth2.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 auth2.c *** auth2.c 2000/08/17 16:17:52 1.1.1.1 --- auth2.c 2000/10/06 20:49:19 *************** *** 61,66 **** --- 61,71 ---- # include <siad.h> #endif + #ifdef HAVE_BSD_AUTH + # include <login_cap.h> + # include <bsd_auth.h> + #endif + /* import */ extern ServerOptions options; extern unsigned char *session_id2; *************** *** 262,268 **** return(sia_validate_user(NULL, saved_argc, saved_argv, get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, "") == SIASUCCESS); ! #else /* !HAVE_OSF_SIA && !USE_PAM */ return auth_password(pw, ""); #endif /* USE_PAM */ } --- 267,275 ---- return(sia_validate_user(NULL, saved_argc, saved_argv, get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, "") == SIASUCCESS); ! #elif defined(HAVE_BSD_AUTH) ! return auth_userokay(authctxt->user, NULL, "auth-ssh", ""); ! #else /* !HAVE_OSF_SIA && !USE_PAM && !HAVE_BSD_AUTH */ return auth_password(pw, ""); #endif /* USE_PAM */ } *************** *** 289,295 **** sia_validate_user(NULL, saved_argc, saved_argv, get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, password) == SIASUCCESS) ! #else /* !USE_PAM && !HAVE_OSF_SIA */ auth_password(pw, password) == 1) #endif /* USE_PAM */ authenticated = 1; --- 296,304 ---- sia_validate_user(NULL, saved_argc, saved_argv, get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, password) == SIASUCCESS) ! #elif defined(HAVE_BSD_AUTH) ! auth_userokay(authctxt->user, NULL, "auth-ssh", password) != 0) ! #else /* !USE_PAM && !HAVE_OSF_SIA && !HAVE_BSD_AUTH */ auth_password(pw, password) == 1) #endif /* USE_PAM */ authenticated = 1; *************** *** 397,403 **** --- 406,424 ---- authctxt->user = xstrdup(u); authctxt->service = xstrdup(s); setproctitle("%s", u); + #ifdef HAVE_BSD_AUTH + { + /* user may contain requested auth type */ + char *p; + if ((p = strchr(u, ':')) != NULL) + *p = '\0'; + pw = getpwnam(u); + if (p != NULL) + *p = ':'; + } + #else pw = getpwnam(u); + #endif if (!pw || !allowed_user(pw)) { log("auth_set_user: illegal user %s", u); return NULL; *************** *** 413,418 **** --- 434,442 ---- copy->pw_gid = pw->pw_gid; copy->pw_dir = xstrdup(pw->pw_dir); copy->pw_shell = xstrdup(pw->pw_shell); + #if defined(BSD) && BSD >= 199506 + copy->pw_class = xstrdup(pw->pw_class); + #endif authctxt->valid = 1; } else { if (strcmp(u, authctxt->user) != 0 || Index: session.c ==================================================================RCS file: /master/contrib/openssh/session.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 session.c *** session.c 2000/08/17 16:17:59 1.1.1.1 --- session.c 2000/10/06 21:03:25 *************** *** 32,37 **** --- 32,41 ---- #include <proj.h> #endif /* WITH_IRIX_PROJECT */ + #ifdef HAVE_SETUSERCONTEXT + #include <login_cap.h> + #endif + #if defined(HAVE_USERSEC_H) #include <usersec.h> #endif *************** *** 900,905 **** --- 904,912 ---- #ifdef WITH_IRIX_PROJECT prid_t projid; #endif /* WITH_IRIX_PROJECT */ + #ifdef HAVE_SETUSERCONTEXT + login_cap_t *lc; + #endif /* HAVE_SETUSERCONTEXT */ /* login(1) is only called if we execute the login shell */ if (options.use_login && command != NULL) *************** *** 927,932 **** --- 934,940 ---- /* Login(1) does this as well, and it needs uid 0 for the "-h" switch, so we let login(1) to this for us. */ if (!options.use_login) { + #ifndef HAVE_SETUSERCONTEXT #ifdef HAVE_OSF_SIA extern char **saved_argv; extern int saved_argc; *************** *** 984,989 **** --- 992,1002 ---- if (getuid() != pw->pw_uid || geteuid() != pw->pw_uid) fatal("Failed to set uids to %d.", (int) pw->pw_uid); #endif /* HAVE_OSF_SIA */ + #else /* HAVE_SETUSERCONTEXT*/ + lc = login_getclass(pw->pw_class); + if (setusercontext(lc, pw, pw->pw_uid, LOGIN_SETALL) < 0) + fatal("setusercontext failed."); + #endif /* HAVE_SETUSERCONTEXT */ } /* * Get the shell from the password data. An empty shell field is *************** *** 1013,1019 **** --- 1026,1038 ---- child_set_env(&env, &envsize, "USER", pw->pw_name); child_set_env(&env, &envsize, "LOGNAME", pw->pw_name); child_set_env(&env, &envsize, "HOME", pw->pw_dir); + #ifdef HAVE_SETUSERCONTEXT + /* update the path to the one setusercontext set for us */ + if (getenv("PATH")) + child_set_env(&env, &envsize, "PATH", getenv("PATH")); + #else child_set_env(&env, &envsize, "PATH", _PATH_STDPATH); + #endif snprintf(buf, sizeof buf, "%.200s/%.50s", _PATH_MAILDIR, pw->pw_name); Index: ssh.c ==================================================================RCS file: /master/contrib/openssh/ssh.c,v retrieving revision 1.1.1.1 diff -c -r1.1.1.1 ssh.c *** ssh.c 2000/08/17 16:18:00 1.1.1.1 --- ssh.c 2000/10/06 20:44:07 *************** *** 492,497 **** --- 492,500 ---- pwcopy.pw_gid = pw->pw_gid; pwcopy.pw_dir = xstrdup(pw->pw_dir); pwcopy.pw_shell = xstrdup(pw->pw_shell); + #if defined(BSD) && BSD >= 199506 + pwcopy.pw_class = xstrdup(pw->pw_class); + #endif pw = &pwcopy; /* Initialize "log" output. Since we are the client all output