1 /* 2 * 3 * Copyright (c) 2001 Gert Doering. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 #include "includes.h" 27 #include "auth.h" 28 #include "ssh.h" 29 #include "log.h" 30 #include "servconf.h" 31 #include "canohost.h" 32 #include "xmalloc.h" 33 #include "buffer.h" 34 35 #ifdef _AIX 36 37 #include <uinfo.h> 38 #include "port-aix.h" 39 40 extern ServerOptions options; 41 extern Buffer loginmsg; 42 43 # ifdef HAVE_SETAUTHDB 44 static char old_registry[REGISTRY_SIZE] = ""; 45 # endif 46 47 /* 48 * AIX has a "usrinfo" area where logname and other stuff is stored - 49 * a few applications actually use this and die if it's not set 50 * 51 * NOTE: TTY= should be set, but since no one uses it and it's hard to 52 * acquire due to privsep code. We will just drop support. 53 */ 54 void 55 aix_usrinfo(struct passwd *pw) 56 { 57 u_int i; 58 size_t len; 59 char *cp; 60 61 len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name)); 62 cp = xmalloc(len); 63 64 i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0', 65 pw->pw_name, '\0'); 66 if (usrinfo(SETUINFO, cp, i) == -1) 67 fatal("Couldn't set usrinfo: %s", strerror(errno)); 68 debug3("AIX/UsrInfo: set len %d", i); 69 70 xfree(cp); 71 } 72 73 # ifdef WITH_AIXAUTHENTICATE 74 /* 75 * Remove embedded newlines in string (if any). 76 * Used before logging messages returned by AIX authentication functions 77 * so the message is logged on one line. 78 */ 79 void 80 aix_remove_embedded_newlines(char *p) 81 { 82 if (p == NULL) 83 return; 84 85 for (; *p; p++) { 86 if (*p == '\n') 87 *p = ' '; 88 } 89 /* Remove trailing whitespace */ 90 if (*--p == ' ') 91 *p = '\0'; 92 } 93 94 /* 95 * Do authentication via AIX's authenticate routine. We loop until the 96 * reenter parameter is 0, but normally authenticate is called only once. 97 * 98 * Note: this function returns 1 on success, whereas AIX's authenticate() 99 * returns 0. 100 */ 101 int 102 sys_auth_passwd(Authctxt *ctxt, const char *password) 103 { 104 char *authmsg = NULL, *msg, *name = ctxt->pw->pw_name; 105 int authsuccess = 0, expired, reenter, result; 106 107 do { 108 result = authenticate((char *)name, (char *)password, &reenter, 109 &authmsg); 110 aix_remove_embedded_newlines(authmsg); 111 debug3("AIX/authenticate result %d, msg %.100s", result, 112 authmsg); 113 } while (reenter); 114 115 if (result == 0) { 116 authsuccess = 1; 117 118 /* 119 * Record successful login. We don't have a pty yet, so just 120 * label the line as "ssh" 121 */ 122 aix_setauthdb(name); 123 124 /* 125 * Check if the user's password is expired. 126 */ 127 expired = passwdexpired(name, &msg); 128 if (msg && *msg) { 129 buffer_append(&loginmsg, msg, strlen(msg)); 130 aix_remove_embedded_newlines(msg); 131 } 132 debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); 133 134 switch (expired) { 135 case 0: /* password not expired */ 136 break; 137 case 1: /* expired, password change required */ 138 ctxt->force_pwchange = 1; 139 disable_forwarding(); 140 break; 141 default: /* user can't change(2) or other error (-1) */ 142 logit("Password can't be changed for user %s: %.100s", 143 name, msg); 144 if (msg) 145 xfree(msg); 146 authsuccess = 0; 147 } 148 149 aix_restoreauthdb(); 150 } 151 152 if (authmsg != NULL) 153 xfree(authmsg); 154 155 return authsuccess; 156 } 157 158 /* 159 * Check if specified account is permitted to log in. 160 * Returns 1 if login is allowed, 0 if not allowed. 161 */ 162 int 163 sys_auth_allowed_user(struct passwd *pw) 164 { 165 char *msg = NULL; 166 int result, permitted = 0; 167 struct stat st; 168 169 /* 170 * Don't perform checks for root account (PermitRootLogin controls 171 * logins via * ssh) or if running as non-root user (since 172 * loginrestrictions will always fail due to insufficient privilege). 173 */ 174 if (pw->pw_uid == 0 || geteuid() != 0) { 175 debug3("%s: not checking", __func__); 176 return 1; 177 } 178 179 result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg); 180 if (result == 0) 181 permitted = 1; 182 /* 183 * If restricted because /etc/nologin exists, the login will be denied 184 * in session.c after the nologin message is sent, so allow for now 185 * and do not append the returned message. 186 */ 187 if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) 188 permitted = 1; 189 else if (msg != NULL) 190 buffer_append(&loginmsg, msg, strlen(msg)); 191 if (msg == NULL) 192 msg = xstrdup("(none)"); 193 aix_remove_embedded_newlines(msg); 194 debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg); 195 196 if (!permitted) 197 logit("Login restricted for %s: %.100s", pw->pw_name, msg); 198 xfree(msg); 199 return permitted; 200 } 201 202 int 203 sys_auth_record_login(const char *user, const char *host, const char *ttynm) 204 { 205 char *msg; 206 int success = 0; 207 208 aix_setauthdb(user); 209 if (loginsuccess((char *)user, host, ttynm, &msg) == 0) { 210 success = 1; 211 if (msg != NULL) { 212 debug("AIX/loginsuccess: msg %s", __func__, msg); 213 buffer_append(&loginmsg, msg, strlen(msg)); 214 xfree(msg); 215 } 216 } 217 aix_restoreauthdb(); 218 return (success); 219 } 220 221 # ifdef CUSTOM_FAILED_LOGIN 222 /* 223 * record_failed_login: generic "login failed" interface function 224 */ 225 void 226 record_failed_login(const char *user, const char *ttyname) 227 { 228 char *hostname = (char *)get_canonical_hostname(options.use_dns); 229 230 if (geteuid() != 0) 231 return; 232 233 aix_setauthdb(user); 234 # ifdef AIX_LOGINFAILED_4ARG 235 loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH); 236 # else 237 loginfailed((char *)user, hostname, (char *)ttyname); 238 # endif 239 aix_restoreauthdb(); 240 } 241 # endif /* CUSTOM_FAILED_LOGIN */ 242 243 /* 244 * If we have setauthdb, retrieve the password registry for the user's 245 * account then feed it to setauthdb. This will mean that subsequent AIX auth 246 * functions will only use the specified loadable module. If we don't have 247 * setauthdb this is a no-op. 248 */ 249 void 250 aix_setauthdb(const char *user) 251 { 252 # ifdef HAVE_SETAUTHDB 253 char *registry; 254 255 if (setuserdb(S_READ) == -1) { 256 debug3("%s: Could not open userdb to read", __func__); 257 return; 258 } 259 260 if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { 261 if (setauthdb(registry, old_registry) == 0) 262 debug3("AIX/setauthdb set registry '%s'", registry); 263 else 264 debug3("AIX/setauthdb set registry '%s' failed: %s", 265 registry, strerror(errno)); 266 } else 267 debug3("%s: Could not read S_REGISTRY for user: %s", __func__, 268 strerror(errno)); 269 enduserdb(); 270 # endif /* HAVE_SETAUTHDB */ 271 } 272 273 /* 274 * Restore the user's registry settings from old_registry. 275 * Note that if the first aix_setauthdb fails, setauthdb("") is still safe 276 * (it restores the system default behaviour). If we don't have setauthdb, 277 * this is a no-op. 278 */ 279 void 280 aix_restoreauthdb(void) 281 { 282 # ifdef HAVE_SETAUTHDB 283 if (setauthdb(old_registry, NULL) == 0) 284 debug3("%s: restoring old registry '%s'", __func__, 285 old_registry); 286 else 287 debug3("%s: failed to restore old registry %s", __func__, 288 old_registry); 289 # endif /* HAVE_SETAUTHDB */ 290 } 291 292 # endif /* WITH_AIXAUTHENTICATE */ 293 294 #endif /* _AIX */ 295