14b17dab0SDag-Erling Smørgrav /* 24b17dab0SDag-Erling Smørgrav * 34b17dab0SDag-Erling Smørgrav * Copyright (c) 2001 Gert Doering. All rights reserved. 4d4af9e69SDag-Erling Smørgrav * Copyright (c) 2003,2004,2005,2006 Darren Tucker. All rights reserved. 54b17dab0SDag-Erling Smørgrav * 64b17dab0SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 74b17dab0SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 84b17dab0SDag-Erling Smørgrav * are met: 94b17dab0SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 104b17dab0SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 114b17dab0SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 124b17dab0SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 134b17dab0SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 144b17dab0SDag-Erling Smørgrav * 154b17dab0SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 164b17dab0SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 174b17dab0SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 184b17dab0SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 194b17dab0SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 204b17dab0SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 214b17dab0SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 224b17dab0SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 234b17dab0SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 244b17dab0SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 254b17dab0SDag-Erling Smørgrav * 264b17dab0SDag-Erling Smørgrav */ 2783d2307dSDag-Erling Smørgrav #include "includes.h" 28761efaa7SDag-Erling Smørgrav 29761efaa7SDag-Erling Smørgrav #include "xmalloc.h" 30761efaa7SDag-Erling Smørgrav #include "buffer.h" 31761efaa7SDag-Erling Smørgrav #include "key.h" 32761efaa7SDag-Erling Smørgrav #include "hostfile.h" 33efcad6b7SDag-Erling Smørgrav #include "auth.h" 34d95e11bfSDag-Erling Smørgrav #include "ssh.h" 35d95e11bfSDag-Erling Smørgrav #include "log.h" 3683d2307dSDag-Erling Smørgrav 3783d2307dSDag-Erling Smørgrav #ifdef _AIX 3883d2307dSDag-Erling Smørgrav 39761efaa7SDag-Erling Smørgrav #include <errno.h> 40761efaa7SDag-Erling Smørgrav #if defined(HAVE_NETDB_H) 41761efaa7SDag-Erling Smørgrav # include <netdb.h> 42761efaa7SDag-Erling Smørgrav #endif 4383d2307dSDag-Erling Smørgrav #include <uinfo.h> 44761efaa7SDag-Erling Smørgrav #include <stdarg.h> 45761efaa7SDag-Erling Smørgrav #include <string.h> 46761efaa7SDag-Erling Smørgrav #include <unistd.h> 475e8dbd04SDag-Erling Smørgrav #include <sys/socket.h> 48761efaa7SDag-Erling Smørgrav 49761efaa7SDag-Erling Smørgrav #ifdef WITH_AIXAUTHENTICATE 50761efaa7SDag-Erling Smørgrav # include <login.h> 51761efaa7SDag-Erling Smørgrav # include <userpw.h> 52761efaa7SDag-Erling Smørgrav # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG) 53761efaa7SDag-Erling Smørgrav # include <sys/audit.h> 54761efaa7SDag-Erling Smørgrav # endif 55761efaa7SDag-Erling Smørgrav # include <usersec.h> 56761efaa7SDag-Erling Smørgrav #endif 57761efaa7SDag-Erling Smørgrav 58d95e11bfSDag-Erling Smørgrav #include "port-aix.h" 59d95e11bfSDag-Erling Smørgrav 607aee6ffeSDag-Erling Smørgrav static char *lastlogin_msg = NULL; 617aee6ffeSDag-Erling Smørgrav 62efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB 63efcad6b7SDag-Erling Smørgrav static char old_registry[REGISTRY_SIZE] = ""; 64efcad6b7SDag-Erling Smørgrav # endif 6583d2307dSDag-Erling Smørgrav 6683d2307dSDag-Erling Smørgrav /* 674b17dab0SDag-Erling Smørgrav * AIX has a "usrinfo" area where logname and other stuff is stored - 684b17dab0SDag-Erling Smørgrav * a few applications actually use this and die if it's not set 694b17dab0SDag-Erling Smørgrav * 704b17dab0SDag-Erling Smørgrav * NOTE: TTY= should be set, but since no one uses it and it's hard to 714b17dab0SDag-Erling Smørgrav * acquire due to privsep code. We will just drop support. 7283d2307dSDag-Erling Smørgrav */ 7383d2307dSDag-Erling Smørgrav void 744b17dab0SDag-Erling Smørgrav aix_usrinfo(struct passwd *pw) 7583d2307dSDag-Erling Smørgrav { 7683d2307dSDag-Erling Smørgrav u_int i; 77d95e11bfSDag-Erling Smørgrav size_t len; 784b17dab0SDag-Erling Smørgrav char *cp; 7983d2307dSDag-Erling Smørgrav 80d95e11bfSDag-Erling Smørgrav len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name)); 81d95e11bfSDag-Erling Smørgrav cp = xmalloc(len); 82d95e11bfSDag-Erling Smørgrav 83d95e11bfSDag-Erling Smørgrav i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0', 84d95e11bfSDag-Erling Smørgrav pw->pw_name, '\0'); 8583d2307dSDag-Erling Smørgrav if (usrinfo(SETUINFO, cp, i) == -1) 8683d2307dSDag-Erling Smørgrav fatal("Couldn't set usrinfo: %s", strerror(errno)); 8783d2307dSDag-Erling Smørgrav debug3("AIX/UsrInfo: set len %d", i); 88d95e11bfSDag-Erling Smørgrav 89*e4a9863fSDag-Erling Smørgrav free(cp); 9083d2307dSDag-Erling Smørgrav } 9183d2307dSDag-Erling Smørgrav 92d95e11bfSDag-Erling Smørgrav # ifdef WITH_AIXAUTHENTICATE 93d95e11bfSDag-Erling Smørgrav /* 94d95e11bfSDag-Erling Smørgrav * Remove embedded newlines in string (if any). 95d95e11bfSDag-Erling Smørgrav * Used before logging messages returned by AIX authentication functions 96d95e11bfSDag-Erling Smørgrav * so the message is logged on one line. 97d95e11bfSDag-Erling Smørgrav */ 98d95e11bfSDag-Erling Smørgrav void 99d95e11bfSDag-Erling Smørgrav aix_remove_embedded_newlines(char *p) 100d95e11bfSDag-Erling Smørgrav { 101d95e11bfSDag-Erling Smørgrav if (p == NULL) 102d95e11bfSDag-Erling Smørgrav return; 103d95e11bfSDag-Erling Smørgrav 104d95e11bfSDag-Erling Smørgrav for (; *p; p++) { 105d95e11bfSDag-Erling Smørgrav if (*p == '\n') 106d95e11bfSDag-Erling Smørgrav *p = ' '; 107d95e11bfSDag-Erling Smørgrav } 108d95e11bfSDag-Erling Smørgrav /* Remove trailing whitespace */ 109d95e11bfSDag-Erling Smørgrav if (*--p == ' ') 110d95e11bfSDag-Erling Smørgrav *p = '\0'; 111d95e11bfSDag-Erling Smørgrav } 112efcad6b7SDag-Erling Smørgrav 113efcad6b7SDag-Erling Smørgrav /* 1145e8dbd04SDag-Erling Smørgrav * Test specifically for the case where SYSTEM == NONE and AUTH1 contains 1155e8dbd04SDag-Erling Smørgrav * anything other than NONE or SYSTEM, which indicates that the admin has 1165e8dbd04SDag-Erling Smørgrav * configured the account for purely AUTH1-type authentication. 1175e8dbd04SDag-Erling Smørgrav * 1185e8dbd04SDag-Erling Smørgrav * Since authenticate() doesn't check AUTH1, and sshd can't sanely support 1195e8dbd04SDag-Erling Smørgrav * AUTH1 itself, in such a case authenticate() will allow access without 1205e8dbd04SDag-Erling Smørgrav * authentation, which is almost certainly not what the admin intends. 1215e8dbd04SDag-Erling Smørgrav * 1225e8dbd04SDag-Erling Smørgrav * (The native tools, eg login, will process the AUTH1 list in addition to 1235e8dbd04SDag-Erling Smørgrav * the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods 1245e8dbd04SDag-Erling Smørgrav * have been deprecated since AIX 4.2.x and would be very difficult for sshd 1255e8dbd04SDag-Erling Smørgrav * to support. 1265e8dbd04SDag-Erling Smørgrav * 1275e8dbd04SDag-Erling Smørgrav * Returns 0 if an unsupportable combination is found, 1 otherwise. 1285e8dbd04SDag-Erling Smørgrav */ 1295e8dbd04SDag-Erling Smørgrav static int 1305e8dbd04SDag-Erling Smørgrav aix_valid_authentications(const char *user) 1315e8dbd04SDag-Erling Smørgrav { 1325e8dbd04SDag-Erling Smørgrav char *auth1, *sys, *p; 1335e8dbd04SDag-Erling Smørgrav int valid = 1; 1345e8dbd04SDag-Erling Smørgrav 1355e8dbd04SDag-Erling Smørgrav if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) { 1365e8dbd04SDag-Erling Smørgrav logit("Can't retrieve attribute SYSTEM for %s: %.100s", 1375e8dbd04SDag-Erling Smørgrav user, strerror(errno)); 1385e8dbd04SDag-Erling Smørgrav return 0; 1395e8dbd04SDag-Erling Smørgrav } 1405e8dbd04SDag-Erling Smørgrav 1415e8dbd04SDag-Erling Smørgrav debug3("AIX SYSTEM attribute %s", sys); 1425e8dbd04SDag-Erling Smørgrav if (strcmp(sys, "NONE") != 0) 1435e8dbd04SDag-Erling Smørgrav return 1; /* not "NONE", so is OK */ 1445e8dbd04SDag-Erling Smørgrav 1455e8dbd04SDag-Erling Smørgrav if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) { 1465e8dbd04SDag-Erling Smørgrav logit("Can't retrieve attribute auth1 for %s: %.100s", 1475e8dbd04SDag-Erling Smørgrav user, strerror(errno)); 1485e8dbd04SDag-Erling Smørgrav return 0; 1495e8dbd04SDag-Erling Smørgrav } 1505e8dbd04SDag-Erling Smørgrav 1515e8dbd04SDag-Erling Smørgrav p = auth1; 1525e8dbd04SDag-Erling Smørgrav /* A SEC_LIST is concatenated strings, ending with two NULs. */ 1535e8dbd04SDag-Erling Smørgrav while (p[0] != '\0' && p[1] != '\0') { 1545e8dbd04SDag-Erling Smørgrav debug3("AIX auth1 attribute list member %s", p); 1555e8dbd04SDag-Erling Smørgrav if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) { 1565e8dbd04SDag-Erling Smørgrav logit("Account %s has unsupported auth1 value '%s'", 1575e8dbd04SDag-Erling Smørgrav user, p); 1585e8dbd04SDag-Erling Smørgrav valid = 0; 1595e8dbd04SDag-Erling Smørgrav } 1605e8dbd04SDag-Erling Smørgrav p += strlen(p) + 1; 1615e8dbd04SDag-Erling Smørgrav } 1625e8dbd04SDag-Erling Smørgrav 1635e8dbd04SDag-Erling Smørgrav return (valid); 1645e8dbd04SDag-Erling Smørgrav } 1655e8dbd04SDag-Erling Smørgrav 1665e8dbd04SDag-Erling Smørgrav /* 167efcad6b7SDag-Erling Smørgrav * Do authentication via AIX's authenticate routine. We loop until the 168efcad6b7SDag-Erling Smørgrav * reenter parameter is 0, but normally authenticate is called only once. 169efcad6b7SDag-Erling Smørgrav * 170efcad6b7SDag-Erling Smørgrav * Note: this function returns 1 on success, whereas AIX's authenticate() 171efcad6b7SDag-Erling Smørgrav * returns 0. 172efcad6b7SDag-Erling Smørgrav */ 173efcad6b7SDag-Erling Smørgrav int 1744518870cSDag-Erling Smørgrav sys_auth_passwd(Authctxt *ctxt, const char *password) 175efcad6b7SDag-Erling Smørgrav { 176043840dfSDag-Erling Smørgrav char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name; 177efcad6b7SDag-Erling Smørgrav int authsuccess = 0, expired, reenter, result; 178efcad6b7SDag-Erling Smørgrav 179efcad6b7SDag-Erling Smørgrav do { 180efcad6b7SDag-Erling Smørgrav result = authenticate((char *)name, (char *)password, &reenter, 181efcad6b7SDag-Erling Smørgrav &authmsg); 182efcad6b7SDag-Erling Smørgrav aix_remove_embedded_newlines(authmsg); 183043840dfSDag-Erling Smørgrav debug3("AIX/authenticate result %d, authmsg %.100s", result, 184efcad6b7SDag-Erling Smørgrav authmsg); 185efcad6b7SDag-Erling Smørgrav } while (reenter); 186efcad6b7SDag-Erling Smørgrav 1875e8dbd04SDag-Erling Smørgrav if (!aix_valid_authentications(name)) 1885e8dbd04SDag-Erling Smørgrav result = -1; 1895e8dbd04SDag-Erling Smørgrav 190efcad6b7SDag-Erling Smørgrav if (result == 0) { 191efcad6b7SDag-Erling Smørgrav authsuccess = 1; 192efcad6b7SDag-Erling Smørgrav 193efcad6b7SDag-Erling Smørgrav /* 194efcad6b7SDag-Erling Smørgrav * Record successful login. We don't have a pty yet, so just 195efcad6b7SDag-Erling Smørgrav * label the line as "ssh" 196efcad6b7SDag-Erling Smørgrav */ 197efcad6b7SDag-Erling Smørgrav aix_setauthdb(name); 198efcad6b7SDag-Erling Smørgrav 199efcad6b7SDag-Erling Smørgrav /* 200efcad6b7SDag-Erling Smørgrav * Check if the user's password is expired. 201efcad6b7SDag-Erling Smørgrav */ 202efcad6b7SDag-Erling Smørgrav expired = passwdexpired(name, &msg); 203efcad6b7SDag-Erling Smørgrav if (msg && *msg) { 2044518870cSDag-Erling Smørgrav buffer_append(ctxt->loginmsg, msg, strlen(msg)); 205efcad6b7SDag-Erling Smørgrav aix_remove_embedded_newlines(msg); 206efcad6b7SDag-Erling Smørgrav } 207efcad6b7SDag-Erling Smørgrav debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); 208efcad6b7SDag-Erling Smørgrav 209efcad6b7SDag-Erling Smørgrav switch (expired) { 210efcad6b7SDag-Erling Smørgrav case 0: /* password not expired */ 211efcad6b7SDag-Erling Smørgrav break; 212efcad6b7SDag-Erling Smørgrav case 1: /* expired, password change required */ 213efcad6b7SDag-Erling Smørgrav ctxt->force_pwchange = 1; 214efcad6b7SDag-Erling Smørgrav break; 215efcad6b7SDag-Erling Smørgrav default: /* user can't change(2) or other error (-1) */ 216efcad6b7SDag-Erling Smørgrav logit("Password can't be changed for user %s: %.100s", 217efcad6b7SDag-Erling Smørgrav name, msg); 218*e4a9863fSDag-Erling Smørgrav free(msg); 219efcad6b7SDag-Erling Smørgrav authsuccess = 0; 220efcad6b7SDag-Erling Smørgrav } 221efcad6b7SDag-Erling Smørgrav 222efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(); 223efcad6b7SDag-Erling Smørgrav } 224efcad6b7SDag-Erling Smørgrav 225*e4a9863fSDag-Erling Smørgrav free(authmsg); 226efcad6b7SDag-Erling Smørgrav 227efcad6b7SDag-Erling Smørgrav return authsuccess; 228efcad6b7SDag-Erling Smørgrav } 229d95e11bfSDag-Erling Smørgrav 230d74d50a8SDag-Erling Smørgrav /* 231d74d50a8SDag-Erling Smørgrav * Check if specified account is permitted to log in. 232d74d50a8SDag-Erling Smørgrav * Returns 1 if login is allowed, 0 if not allowed. 233d74d50a8SDag-Erling Smørgrav */ 234d74d50a8SDag-Erling Smørgrav int 2355e8dbd04SDag-Erling Smørgrav sys_auth_allowed_user(struct passwd *pw, Buffer *loginmsg) 236d74d50a8SDag-Erling Smørgrav { 237d74d50a8SDag-Erling Smørgrav char *msg = NULL; 238d74d50a8SDag-Erling Smørgrav int result, permitted = 0; 239d74d50a8SDag-Erling Smørgrav struct stat st; 240d74d50a8SDag-Erling Smørgrav 241d74d50a8SDag-Erling Smørgrav /* 242d74d50a8SDag-Erling Smørgrav * Don't perform checks for root account (PermitRootLogin controls 243d4af9e69SDag-Erling Smørgrav * logins via ssh) or if running as non-root user (since 244d74d50a8SDag-Erling Smørgrav * loginrestrictions will always fail due to insufficient privilege). 245d74d50a8SDag-Erling Smørgrav */ 246d74d50a8SDag-Erling Smørgrav if (pw->pw_uid == 0 || geteuid() != 0) { 247d74d50a8SDag-Erling Smørgrav debug3("%s: not checking", __func__); 248d74d50a8SDag-Erling Smørgrav return 1; 249d74d50a8SDag-Erling Smørgrav } 250d74d50a8SDag-Erling Smørgrav 251d74d50a8SDag-Erling Smørgrav result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg); 252d74d50a8SDag-Erling Smørgrav if (result == 0) 253d74d50a8SDag-Erling Smørgrav permitted = 1; 254d74d50a8SDag-Erling Smørgrav /* 255d74d50a8SDag-Erling Smørgrav * If restricted because /etc/nologin exists, the login will be denied 256d74d50a8SDag-Erling Smørgrav * in session.c after the nologin message is sent, so allow for now 257d74d50a8SDag-Erling Smørgrav * and do not append the returned message. 258d74d50a8SDag-Erling Smørgrav */ 259d74d50a8SDag-Erling Smørgrav if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) 260d74d50a8SDag-Erling Smørgrav permitted = 1; 261d74d50a8SDag-Erling Smørgrav else if (msg != NULL) 2625e8dbd04SDag-Erling Smørgrav buffer_append(loginmsg, msg, strlen(msg)); 263d74d50a8SDag-Erling Smørgrav if (msg == NULL) 264d74d50a8SDag-Erling Smørgrav msg = xstrdup("(none)"); 265d74d50a8SDag-Erling Smørgrav aix_remove_embedded_newlines(msg); 266d74d50a8SDag-Erling Smørgrav debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg); 267d74d50a8SDag-Erling Smørgrav 268d74d50a8SDag-Erling Smørgrav if (!permitted) 269d74d50a8SDag-Erling Smørgrav logit("Login restricted for %s: %.100s", pw->pw_name, msg); 270*e4a9863fSDag-Erling Smørgrav free(msg); 271d74d50a8SDag-Erling Smørgrav return permitted; 272d74d50a8SDag-Erling Smørgrav } 273d74d50a8SDag-Erling Smørgrav 274d74d50a8SDag-Erling Smørgrav int 2755e8dbd04SDag-Erling Smørgrav sys_auth_record_login(const char *user, const char *host, const char *ttynm, 2765e8dbd04SDag-Erling Smørgrav Buffer *loginmsg) 277d74d50a8SDag-Erling Smørgrav { 278043840dfSDag-Erling Smørgrav char *msg = NULL; 279d74d50a8SDag-Erling Smørgrav int success = 0; 280d74d50a8SDag-Erling Smørgrav 281d74d50a8SDag-Erling Smørgrav aix_setauthdb(user); 2825e8dbd04SDag-Erling Smørgrav if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) { 283d74d50a8SDag-Erling Smørgrav success = 1; 2847aee6ffeSDag-Erling Smørgrav if (msg != NULL) { 2855e8dbd04SDag-Erling Smørgrav debug("AIX/loginsuccess: msg %s", msg); 2867aee6ffeSDag-Erling Smørgrav if (lastlogin_msg == NULL) 2877aee6ffeSDag-Erling Smørgrav lastlogin_msg = msg; 288d74d50a8SDag-Erling Smørgrav } 289d74d50a8SDag-Erling Smørgrav } 290d74d50a8SDag-Erling Smørgrav aix_restoreauthdb(); 291d74d50a8SDag-Erling Smørgrav return (success); 292d74d50a8SDag-Erling Smørgrav } 293d74d50a8SDag-Erling Smørgrav 2947aee6ffeSDag-Erling Smørgrav char * 2957aee6ffeSDag-Erling Smørgrav sys_auth_get_lastlogin_msg(const char *user, uid_t uid) 2967aee6ffeSDag-Erling Smørgrav { 2977aee6ffeSDag-Erling Smørgrav char *msg = lastlogin_msg; 2987aee6ffeSDag-Erling Smørgrav 2997aee6ffeSDag-Erling Smørgrav lastlogin_msg = NULL; 3007aee6ffeSDag-Erling Smørgrav return msg; 3017aee6ffeSDag-Erling Smørgrav } 3027aee6ffeSDag-Erling Smørgrav 303d95e11bfSDag-Erling Smørgrav # ifdef CUSTOM_FAILED_LOGIN 304d95e11bfSDag-Erling Smørgrav /* 305d95e11bfSDag-Erling Smørgrav * record_failed_login: generic "login failed" interface function 306d95e11bfSDag-Erling Smørgrav */ 307d95e11bfSDag-Erling Smørgrav void 3085e8dbd04SDag-Erling Smørgrav record_failed_login(const char *user, const char *hostname, const char *ttyname) 309d95e11bfSDag-Erling Smørgrav { 310d95e11bfSDag-Erling Smørgrav if (geteuid() != 0) 311d95e11bfSDag-Erling Smørgrav return; 312d95e11bfSDag-Erling Smørgrav 313d95e11bfSDag-Erling Smørgrav aix_setauthdb(user); 314d95e11bfSDag-Erling Smørgrav # ifdef AIX_LOGINFAILED_4ARG 3155e8dbd04SDag-Erling Smørgrav loginfailed((char *)user, (char *)hostname, (char *)ttyname, 3165e8dbd04SDag-Erling Smørgrav AUDIT_FAIL_AUTH); 317d95e11bfSDag-Erling Smørgrav # else 3185e8dbd04SDag-Erling Smørgrav loginfailed((char *)user, (char *)hostname, (char *)ttyname); 319d95e11bfSDag-Erling Smørgrav # endif 320efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(); 321d95e11bfSDag-Erling Smørgrav } 322efcad6b7SDag-Erling Smørgrav # endif /* CUSTOM_FAILED_LOGIN */ 323d95e11bfSDag-Erling Smørgrav 324d95e11bfSDag-Erling Smørgrav /* 325d95e11bfSDag-Erling Smørgrav * If we have setauthdb, retrieve the password registry for the user's 326efcad6b7SDag-Erling Smørgrav * account then feed it to setauthdb. This will mean that subsequent AIX auth 327efcad6b7SDag-Erling Smørgrav * functions will only use the specified loadable module. If we don't have 328efcad6b7SDag-Erling Smørgrav * setauthdb this is a no-op. 329d95e11bfSDag-Erling Smørgrav */ 330d95e11bfSDag-Erling Smørgrav void 331d95e11bfSDag-Erling Smørgrav aix_setauthdb(const char *user) 332d95e11bfSDag-Erling Smørgrav { 333d95e11bfSDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB 334efcad6b7SDag-Erling Smørgrav char *registry; 335d95e11bfSDag-Erling Smørgrav 336d95e11bfSDag-Erling Smørgrav if (setuserdb(S_READ) == -1) { 337d95e11bfSDag-Erling Smørgrav debug3("%s: Could not open userdb to read", __func__); 338d95e11bfSDag-Erling Smørgrav return; 339d95e11bfSDag-Erling Smørgrav } 340d95e11bfSDag-Erling Smørgrav 341d95e11bfSDag-Erling Smørgrav if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { 342efcad6b7SDag-Erling Smørgrav if (setauthdb(registry, old_registry) == 0) 343efcad6b7SDag-Erling Smørgrav debug3("AIX/setauthdb set registry '%s'", registry); 344d95e11bfSDag-Erling Smørgrav else 345efcad6b7SDag-Erling Smørgrav debug3("AIX/setauthdb set registry '%s' failed: %s", 346efcad6b7SDag-Erling Smørgrav registry, strerror(errno)); 347d95e11bfSDag-Erling Smørgrav } else 348d95e11bfSDag-Erling Smørgrav debug3("%s: Could not read S_REGISTRY for user: %s", __func__, 349d95e11bfSDag-Erling Smørgrav strerror(errno)); 350d95e11bfSDag-Erling Smørgrav enduserdb(); 351efcad6b7SDag-Erling Smørgrav # endif /* HAVE_SETAUTHDB */ 352d95e11bfSDag-Erling Smørgrav } 35383d2307dSDag-Erling Smørgrav 354efcad6b7SDag-Erling Smørgrav /* 355efcad6b7SDag-Erling Smørgrav * Restore the user's registry settings from old_registry. 356efcad6b7SDag-Erling Smørgrav * Note that if the first aix_setauthdb fails, setauthdb("") is still safe 357efcad6b7SDag-Erling Smørgrav * (it restores the system default behaviour). If we don't have setauthdb, 358efcad6b7SDag-Erling Smørgrav * this is a no-op. 359efcad6b7SDag-Erling Smørgrav */ 360efcad6b7SDag-Erling Smørgrav void 361efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(void) 362efcad6b7SDag-Erling Smørgrav { 363efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB 364efcad6b7SDag-Erling Smørgrav if (setauthdb(old_registry, NULL) == 0) 365efcad6b7SDag-Erling Smørgrav debug3("%s: restoring old registry '%s'", __func__, 366efcad6b7SDag-Erling Smørgrav old_registry); 367efcad6b7SDag-Erling Smørgrav else 368efcad6b7SDag-Erling Smørgrav debug3("%s: failed to restore old registry %s", __func__, 369efcad6b7SDag-Erling Smørgrav old_registry); 370efcad6b7SDag-Erling Smørgrav # endif /* HAVE_SETAUTHDB */ 371efcad6b7SDag-Erling Smørgrav } 372efcad6b7SDag-Erling Smørgrav 373efcad6b7SDag-Erling Smørgrav # endif /* WITH_AIXAUTHENTICATE */ 374efcad6b7SDag-Erling Smørgrav 375b15c8340SDag-Erling Smørgrav # ifdef USE_AIX_KRB_NAME 376b15c8340SDag-Erling Smørgrav /* 377b15c8340SDag-Erling Smørgrav * aix_krb5_get_principal_name: returns the user's kerberos client principal name if 378b15c8340SDag-Erling Smørgrav * configured, otherwise NULL. Caller must free returned string. 379b15c8340SDag-Erling Smørgrav */ 380b15c8340SDag-Erling Smørgrav char * 381b15c8340SDag-Erling Smørgrav aix_krb5_get_principal_name(char *pw_name) 382b15c8340SDag-Erling Smørgrav { 383b15c8340SDag-Erling Smørgrav char *authname = NULL, *authdomain = NULL, *principal = NULL; 384b15c8340SDag-Erling Smørgrav 385b15c8340SDag-Erling Smørgrav setuserdb(S_READ); 386b15c8340SDag-Erling Smørgrav if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0) 387b15c8340SDag-Erling Smørgrav debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno)); 388b15c8340SDag-Erling Smørgrav if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0) 389b15c8340SDag-Erling Smørgrav debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno)); 390b15c8340SDag-Erling Smørgrav 391b15c8340SDag-Erling Smørgrav if (authdomain != NULL) 392b15c8340SDag-Erling Smørgrav xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain); 393b15c8340SDag-Erling Smørgrav else if (authname != NULL) 394b15c8340SDag-Erling Smørgrav principal = xstrdup(authname); 395b15c8340SDag-Erling Smørgrav enduserdb(); 396b15c8340SDag-Erling Smørgrav return principal; 397b15c8340SDag-Erling Smørgrav } 398b15c8340SDag-Erling Smørgrav # endif /* USE_AIX_KRB_NAME */ 399b15c8340SDag-Erling Smørgrav 4005e8dbd04SDag-Erling Smørgrav # if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO) 4015e8dbd04SDag-Erling Smørgrav # undef getnameinfo 4025e8dbd04SDag-Erling Smørgrav /* 4035e8dbd04SDag-Erling Smørgrav * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros 4045e8dbd04SDag-Erling Smørgrav * IPv6 address into its textual representation ("::"), so we wrap it 4055e8dbd04SDag-Erling Smørgrav * with a function that will. 4065e8dbd04SDag-Erling Smørgrav */ 4075e8dbd04SDag-Erling Smørgrav int 4085e8dbd04SDag-Erling Smørgrav sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, 4095e8dbd04SDag-Erling Smørgrav size_t hostlen, char *serv, size_t servlen, int flags) 4105e8dbd04SDag-Erling Smørgrav { 4115e8dbd04SDag-Erling Smørgrav struct sockaddr_in6 *sa6; 4125e8dbd04SDag-Erling Smørgrav u_int32_t *a6; 4135e8dbd04SDag-Erling Smørgrav 4145e8dbd04SDag-Erling Smørgrav if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) && 4155e8dbd04SDag-Erling Smørgrav sa->sa_family == AF_INET6) { 4165e8dbd04SDag-Erling Smørgrav sa6 = (struct sockaddr_in6 *)sa; 4175e8dbd04SDag-Erling Smørgrav a6 = sa6->sin6_addr.u6_addr.u6_addr32; 4185e8dbd04SDag-Erling Smørgrav 4195e8dbd04SDag-Erling Smørgrav if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { 4205e8dbd04SDag-Erling Smørgrav strlcpy(host, "::", hostlen); 4215e8dbd04SDag-Erling Smørgrav snprintf(serv, servlen, "%d", sa6->sin6_port); 4225e8dbd04SDag-Erling Smørgrav return 0; 4235e8dbd04SDag-Erling Smørgrav } 4245e8dbd04SDag-Erling Smørgrav } 4255e8dbd04SDag-Erling Smørgrav return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); 4265e8dbd04SDag-Erling Smørgrav } 4275e8dbd04SDag-Erling Smørgrav # endif /* AIX_GETNAMEINFO_HACK */ 4285e8dbd04SDag-Erling Smørgrav 429d4af9e69SDag-Erling Smørgrav # if defined(USE_GETGRSET) 430d4af9e69SDag-Erling Smørgrav # include <stdlib.h> 431d4af9e69SDag-Erling Smørgrav int 432d4af9e69SDag-Erling Smørgrav getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt) 433d4af9e69SDag-Erling Smørgrav { 434d4af9e69SDag-Erling Smørgrav char *cp, *grplist, *grp; 435d4af9e69SDag-Erling Smørgrav gid_t gid; 436d4af9e69SDag-Erling Smørgrav int ret = 0, ngroups = 0, maxgroups; 437d4af9e69SDag-Erling Smørgrav long l; 438d4af9e69SDag-Erling Smørgrav 439d4af9e69SDag-Erling Smørgrav maxgroups = *grpcnt; 440d4af9e69SDag-Erling Smørgrav 441d4af9e69SDag-Erling Smørgrav if ((cp = grplist = getgrset(user)) == NULL) 442d4af9e69SDag-Erling Smørgrav return -1; 443d4af9e69SDag-Erling Smørgrav 444d4af9e69SDag-Erling Smørgrav /* handle zero-length case */ 445d4af9e69SDag-Erling Smørgrav if (maxgroups <= 0) { 446d4af9e69SDag-Erling Smørgrav *grpcnt = 0; 447d4af9e69SDag-Erling Smørgrav return -1; 448d4af9e69SDag-Erling Smørgrav } 449d4af9e69SDag-Erling Smørgrav 450d4af9e69SDag-Erling Smørgrav /* copy primary group */ 451d4af9e69SDag-Erling Smørgrav groups[ngroups++] = pgid; 452d4af9e69SDag-Erling Smørgrav 453d4af9e69SDag-Erling Smørgrav /* copy each entry from getgrset into group list */ 454d4af9e69SDag-Erling Smørgrav while ((grp = strsep(&grplist, ",")) != NULL) { 455d4af9e69SDag-Erling Smørgrav l = strtol(grp, NULL, 10); 456d4af9e69SDag-Erling Smørgrav if (ngroups >= maxgroups || l == LONG_MIN || l == LONG_MAX) { 457d4af9e69SDag-Erling Smørgrav ret = -1; 458d4af9e69SDag-Erling Smørgrav goto out; 459d4af9e69SDag-Erling Smørgrav } 460d4af9e69SDag-Erling Smørgrav gid = (gid_t)l; 461d4af9e69SDag-Erling Smørgrav if (gid == pgid) 462d4af9e69SDag-Erling Smørgrav continue; /* we have already added primary gid */ 463d4af9e69SDag-Erling Smørgrav groups[ngroups++] = gid; 464d4af9e69SDag-Erling Smørgrav } 465d4af9e69SDag-Erling Smørgrav out: 466d4af9e69SDag-Erling Smørgrav free(cp); 467d4af9e69SDag-Erling Smørgrav *grpcnt = ngroups; 468d4af9e69SDag-Erling Smørgrav return ret; 469d4af9e69SDag-Erling Smørgrav } 470d4af9e69SDag-Erling Smørgrav # endif /* USE_GETGRSET */ 471d4af9e69SDag-Erling Smørgrav 472efcad6b7SDag-Erling Smørgrav #endif /* _AIX */ 473