14b17dab0SDag-Erling Smørgrav /* 24b17dab0SDag-Erling Smørgrav * 34b17dab0SDag-Erling Smørgrav * Copyright (c) 2001 Gert Doering. All rights reserved. 44b17dab0SDag-Erling Smørgrav * 54b17dab0SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 64b17dab0SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 74b17dab0SDag-Erling Smørgrav * are met: 84b17dab0SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 94b17dab0SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer. 104b17dab0SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 114b17dab0SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 124b17dab0SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 134b17dab0SDag-Erling Smørgrav * 144b17dab0SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 154b17dab0SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 164b17dab0SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 174b17dab0SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 184b17dab0SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 194b17dab0SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 204b17dab0SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 214b17dab0SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 224b17dab0SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 234b17dab0SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 244b17dab0SDag-Erling Smørgrav * 254b17dab0SDag-Erling Smørgrav */ 2683d2307dSDag-Erling Smørgrav #include "includes.h" 27efcad6b7SDag-Erling Smørgrav #include "auth.h" 28d95e11bfSDag-Erling Smørgrav #include "ssh.h" 29d95e11bfSDag-Erling Smørgrav #include "log.h" 30d95e11bfSDag-Erling Smørgrav #include "servconf.h" 31d95e11bfSDag-Erling Smørgrav #include "canohost.h" 32d95e11bfSDag-Erling Smørgrav #include "xmalloc.h" 33efcad6b7SDag-Erling Smørgrav #include "buffer.h" 3483d2307dSDag-Erling Smørgrav 3583d2307dSDag-Erling Smørgrav #ifdef _AIX 3683d2307dSDag-Erling Smørgrav 3783d2307dSDag-Erling Smørgrav #include <uinfo.h> 38d95e11bfSDag-Erling Smørgrav #include "port-aix.h" 39d95e11bfSDag-Erling Smørgrav 40d95e11bfSDag-Erling Smørgrav extern ServerOptions options; 41efcad6b7SDag-Erling Smørgrav extern Buffer loginmsg; 42efcad6b7SDag-Erling Smørgrav 43efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB 44efcad6b7SDag-Erling Smørgrav static char old_registry[REGISTRY_SIZE] = ""; 45efcad6b7SDag-Erling Smørgrav # endif 4683d2307dSDag-Erling Smørgrav 4783d2307dSDag-Erling Smørgrav /* 484b17dab0SDag-Erling Smørgrav * AIX has a "usrinfo" area where logname and other stuff is stored - 494b17dab0SDag-Erling Smørgrav * a few applications actually use this and die if it's not set 504b17dab0SDag-Erling Smørgrav * 514b17dab0SDag-Erling Smørgrav * NOTE: TTY= should be set, but since no one uses it and it's hard to 524b17dab0SDag-Erling Smørgrav * acquire due to privsep code. We will just drop support. 5383d2307dSDag-Erling Smørgrav */ 5483d2307dSDag-Erling Smørgrav void 554b17dab0SDag-Erling Smørgrav aix_usrinfo(struct passwd *pw) 5683d2307dSDag-Erling Smørgrav { 5783d2307dSDag-Erling Smørgrav u_int i; 58d95e11bfSDag-Erling Smørgrav size_t len; 594b17dab0SDag-Erling Smørgrav char *cp; 6083d2307dSDag-Erling Smørgrav 61d95e11bfSDag-Erling Smørgrav len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name)); 62d95e11bfSDag-Erling Smørgrav cp = xmalloc(len); 63d95e11bfSDag-Erling Smørgrav 64d95e11bfSDag-Erling Smørgrav i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0', 65d95e11bfSDag-Erling Smørgrav pw->pw_name, '\0'); 6683d2307dSDag-Erling Smørgrav if (usrinfo(SETUINFO, cp, i) == -1) 6783d2307dSDag-Erling Smørgrav fatal("Couldn't set usrinfo: %s", strerror(errno)); 6883d2307dSDag-Erling Smørgrav debug3("AIX/UsrInfo: set len %d", i); 69d95e11bfSDag-Erling Smørgrav 7083d2307dSDag-Erling Smørgrav xfree(cp); 7183d2307dSDag-Erling Smørgrav } 7283d2307dSDag-Erling Smørgrav 73d95e11bfSDag-Erling Smørgrav # ifdef WITH_AIXAUTHENTICATE 74d95e11bfSDag-Erling Smørgrav /* 75d95e11bfSDag-Erling Smørgrav * Remove embedded newlines in string (if any). 76d95e11bfSDag-Erling Smørgrav * Used before logging messages returned by AIX authentication functions 77d95e11bfSDag-Erling Smørgrav * so the message is logged on one line. 78d95e11bfSDag-Erling Smørgrav */ 79d95e11bfSDag-Erling Smørgrav void 80d95e11bfSDag-Erling Smørgrav aix_remove_embedded_newlines(char *p) 81d95e11bfSDag-Erling Smørgrav { 82d95e11bfSDag-Erling Smørgrav if (p == NULL) 83d95e11bfSDag-Erling Smørgrav return; 84d95e11bfSDag-Erling Smørgrav 85d95e11bfSDag-Erling Smørgrav for (; *p; p++) { 86d95e11bfSDag-Erling Smørgrav if (*p == '\n') 87d95e11bfSDag-Erling Smørgrav *p = ' '; 88d95e11bfSDag-Erling Smørgrav } 89d95e11bfSDag-Erling Smørgrav /* Remove trailing whitespace */ 90d95e11bfSDag-Erling Smørgrav if (*--p == ' ') 91d95e11bfSDag-Erling Smørgrav *p = '\0'; 92d95e11bfSDag-Erling Smørgrav } 93efcad6b7SDag-Erling Smørgrav 94efcad6b7SDag-Erling Smørgrav /* 95efcad6b7SDag-Erling Smørgrav * Do authentication via AIX's authenticate routine. We loop until the 96efcad6b7SDag-Erling Smørgrav * reenter parameter is 0, but normally authenticate is called only once. 97efcad6b7SDag-Erling Smørgrav * 98efcad6b7SDag-Erling Smørgrav * Note: this function returns 1 on success, whereas AIX's authenticate() 99efcad6b7SDag-Erling Smørgrav * returns 0. 100efcad6b7SDag-Erling Smørgrav */ 101efcad6b7SDag-Erling Smørgrav int 102efcad6b7SDag-Erling Smørgrav sys_auth_passwd(Authctxt *ctxt, const char *password) 103efcad6b7SDag-Erling Smørgrav { 104efcad6b7SDag-Erling Smørgrav char *authmsg = NULL, *host, *msg, *name = ctxt->pw->pw_name; 105efcad6b7SDag-Erling Smørgrav int authsuccess = 0, expired, reenter, result; 106efcad6b7SDag-Erling Smørgrav 107efcad6b7SDag-Erling Smørgrav do { 108efcad6b7SDag-Erling Smørgrav result = authenticate((char *)name, (char *)password, &reenter, 109efcad6b7SDag-Erling Smørgrav &authmsg); 110efcad6b7SDag-Erling Smørgrav aix_remove_embedded_newlines(authmsg); 111efcad6b7SDag-Erling Smørgrav debug3("AIX/authenticate result %d, msg %.100s", result, 112efcad6b7SDag-Erling Smørgrav authmsg); 113efcad6b7SDag-Erling Smørgrav } while (reenter); 114efcad6b7SDag-Erling Smørgrav 115efcad6b7SDag-Erling Smørgrav if (result == 0) { 116efcad6b7SDag-Erling Smørgrav authsuccess = 1; 117efcad6b7SDag-Erling Smørgrav 118efcad6b7SDag-Erling Smørgrav host = (char *)get_canonical_hostname(options.use_dns); 119efcad6b7SDag-Erling Smørgrav 120efcad6b7SDag-Erling Smørgrav /* 121efcad6b7SDag-Erling Smørgrav * Record successful login. We don't have a pty yet, so just 122efcad6b7SDag-Erling Smørgrav * label the line as "ssh" 123efcad6b7SDag-Erling Smørgrav */ 124efcad6b7SDag-Erling Smørgrav aix_setauthdb(name); 125efcad6b7SDag-Erling Smørgrav if (loginsuccess((char *)name, (char *)host, "ssh", &msg) == 0) { 126efcad6b7SDag-Erling Smørgrav if (msg != NULL) { 127efcad6b7SDag-Erling Smørgrav debug("%s: msg %s", __func__, msg); 128efcad6b7SDag-Erling Smørgrav buffer_append(&loginmsg, msg, strlen(msg)); 129efcad6b7SDag-Erling Smørgrav xfree(msg); 130efcad6b7SDag-Erling Smørgrav } 131efcad6b7SDag-Erling Smørgrav } 132efcad6b7SDag-Erling Smørgrav 133efcad6b7SDag-Erling Smørgrav /* 134efcad6b7SDag-Erling Smørgrav * Check if the user's password is expired. 135efcad6b7SDag-Erling Smørgrav */ 136efcad6b7SDag-Erling Smørgrav expired = passwdexpired(name, &msg); 137efcad6b7SDag-Erling Smørgrav if (msg && *msg) { 138efcad6b7SDag-Erling Smørgrav buffer_append(&loginmsg, msg, strlen(msg)); 139efcad6b7SDag-Erling Smørgrav aix_remove_embedded_newlines(msg); 140efcad6b7SDag-Erling Smørgrav } 141efcad6b7SDag-Erling Smørgrav debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); 142efcad6b7SDag-Erling Smørgrav 143efcad6b7SDag-Erling Smørgrav switch (expired) { 144efcad6b7SDag-Erling Smørgrav case 0: /* password not expired */ 145efcad6b7SDag-Erling Smørgrav break; 146efcad6b7SDag-Erling Smørgrav case 1: /* expired, password change required */ 147efcad6b7SDag-Erling Smørgrav ctxt->force_pwchange = 1; 148efcad6b7SDag-Erling Smørgrav disable_forwarding(); 149efcad6b7SDag-Erling Smørgrav break; 150efcad6b7SDag-Erling Smørgrav default: /* user can't change(2) or other error (-1) */ 151efcad6b7SDag-Erling Smørgrav logit("Password can't be changed for user %s: %.100s", 152efcad6b7SDag-Erling Smørgrav name, msg); 153efcad6b7SDag-Erling Smørgrav if (msg) 154efcad6b7SDag-Erling Smørgrav xfree(msg); 155efcad6b7SDag-Erling Smørgrav authsuccess = 0; 156efcad6b7SDag-Erling Smørgrav } 157efcad6b7SDag-Erling Smørgrav 158efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(); 159efcad6b7SDag-Erling Smørgrav } 160efcad6b7SDag-Erling Smørgrav 161efcad6b7SDag-Erling Smørgrav if (authmsg != NULL) 162efcad6b7SDag-Erling Smørgrav xfree(authmsg); 163efcad6b7SDag-Erling Smørgrav 164efcad6b7SDag-Erling Smørgrav return authsuccess; 165efcad6b7SDag-Erling Smørgrav } 166d95e11bfSDag-Erling Smørgrav 167d95e11bfSDag-Erling Smørgrav # ifdef CUSTOM_FAILED_LOGIN 168d95e11bfSDag-Erling Smørgrav /* 169d95e11bfSDag-Erling Smørgrav * record_failed_login: generic "login failed" interface function 170d95e11bfSDag-Erling Smørgrav */ 171d95e11bfSDag-Erling Smørgrav void 172d95e11bfSDag-Erling Smørgrav record_failed_login(const char *user, const char *ttyname) 173d95e11bfSDag-Erling Smørgrav { 174efcad6b7SDag-Erling Smørgrav char *hostname = (char *)get_canonical_hostname(options.use_dns); 175d95e11bfSDag-Erling Smørgrav 176d95e11bfSDag-Erling Smørgrav if (geteuid() != 0) 177d95e11bfSDag-Erling Smørgrav return; 178d95e11bfSDag-Erling Smørgrav 179d95e11bfSDag-Erling Smørgrav aix_setauthdb(user); 180d95e11bfSDag-Erling Smørgrav # ifdef AIX_LOGINFAILED_4ARG 181d95e11bfSDag-Erling Smørgrav loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH); 182d95e11bfSDag-Erling Smørgrav # else 183d95e11bfSDag-Erling Smørgrav loginfailed((char *)user, hostname, (char *)ttyname); 184d95e11bfSDag-Erling Smørgrav # endif 185efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(); 186d95e11bfSDag-Erling Smørgrav } 187efcad6b7SDag-Erling Smørgrav # endif /* CUSTOM_FAILED_LOGIN */ 188d95e11bfSDag-Erling Smørgrav 189d95e11bfSDag-Erling Smørgrav /* 190d95e11bfSDag-Erling Smørgrav * If we have setauthdb, retrieve the password registry for the user's 191efcad6b7SDag-Erling Smørgrav * account then feed it to setauthdb. This will mean that subsequent AIX auth 192efcad6b7SDag-Erling Smørgrav * functions will only use the specified loadable module. If we don't have 193efcad6b7SDag-Erling Smørgrav * setauthdb this is a no-op. 194d95e11bfSDag-Erling Smørgrav */ 195d95e11bfSDag-Erling Smørgrav void 196d95e11bfSDag-Erling Smørgrav aix_setauthdb(const char *user) 197d95e11bfSDag-Erling Smørgrav { 198d95e11bfSDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB 199efcad6b7SDag-Erling Smørgrav char *registry; 200d95e11bfSDag-Erling Smørgrav 201d95e11bfSDag-Erling Smørgrav if (setuserdb(S_READ) == -1) { 202d95e11bfSDag-Erling Smørgrav debug3("%s: Could not open userdb to read", __func__); 203d95e11bfSDag-Erling Smørgrav return; 204d95e11bfSDag-Erling Smørgrav } 205d95e11bfSDag-Erling Smørgrav 206d95e11bfSDag-Erling Smørgrav if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { 207efcad6b7SDag-Erling Smørgrav if (setauthdb(registry, old_registry) == 0) 208efcad6b7SDag-Erling Smørgrav debug3("AIX/setauthdb set registry '%s'", registry); 209d95e11bfSDag-Erling Smørgrav else 210efcad6b7SDag-Erling Smørgrav debug3("AIX/setauthdb set registry '%s' failed: %s", 211efcad6b7SDag-Erling Smørgrav registry, strerror(errno)); 212d95e11bfSDag-Erling Smørgrav } else 213d95e11bfSDag-Erling Smørgrav debug3("%s: Could not read S_REGISTRY for user: %s", __func__, 214d95e11bfSDag-Erling Smørgrav strerror(errno)); 215d95e11bfSDag-Erling Smørgrav enduserdb(); 216efcad6b7SDag-Erling Smørgrav # endif /* HAVE_SETAUTHDB */ 217d95e11bfSDag-Erling Smørgrav } 21883d2307dSDag-Erling Smørgrav 219efcad6b7SDag-Erling Smørgrav /* 220efcad6b7SDag-Erling Smørgrav * Restore the user's registry settings from old_registry. 221efcad6b7SDag-Erling Smørgrav * Note that if the first aix_setauthdb fails, setauthdb("") is still safe 222efcad6b7SDag-Erling Smørgrav * (it restores the system default behaviour). If we don't have setauthdb, 223efcad6b7SDag-Erling Smørgrav * this is a no-op. 224efcad6b7SDag-Erling Smørgrav */ 225efcad6b7SDag-Erling Smørgrav void 226efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(void) 227efcad6b7SDag-Erling Smørgrav { 228efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB 229efcad6b7SDag-Erling Smørgrav if (setauthdb(old_registry, NULL) == 0) 230efcad6b7SDag-Erling Smørgrav debug3("%s: restoring old registry '%s'", __func__, 231efcad6b7SDag-Erling Smørgrav old_registry); 232efcad6b7SDag-Erling Smørgrav else 233efcad6b7SDag-Erling Smørgrav debug3("%s: failed to restore old registry %s", __func__, 234efcad6b7SDag-Erling Smørgrav old_registry); 235efcad6b7SDag-Erling Smørgrav # endif /* HAVE_SETAUTHDB */ 236efcad6b7SDag-Erling Smørgrav } 237efcad6b7SDag-Erling Smørgrav 238efcad6b7SDag-Erling Smørgrav # endif /* WITH_AIXAUTHENTICATE */ 239efcad6b7SDag-Erling Smørgrav 240efcad6b7SDag-Erling Smørgrav #endif /* _AIX */ 241