Ben Lindstrom | 51b2488 | 2002-07-04 03:08:40 +0000 | [diff] [blame] | 1 | /* |
Ben Lindstrom | 024f08f | 2002-07-07 02:17:36 +0000 | [diff] [blame] | 2 | * |
| 3 | * Copyright (c) 2001 Gert Doering. All rights reserved. |
Darren Tucker | 0f26b13 | 2008-02-28 23:16:04 +1100 | [diff] [blame] | 4 | * Copyright (c) 2003,2004,2005,2006 Darren Tucker. All rights reserved. |
Ben Lindstrom | 024f08f | 2002-07-07 02:17:36 +0000 | [diff] [blame] | 5 | * |
Ben Lindstrom | 51b2488 | 2002-07-04 03:08:40 +0000 | [diff] [blame] | 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions |
| 8 | * are met: |
| 9 | * 1. Redistributions of source code must retain the above copyright |
| 10 | * notice, this list of conditions and the following disclaimer. |
| 11 | * 2. Redistributions in binary form must reproduce the above copyright |
| 12 | * notice, this list of conditions and the following disclaimer in the |
| 13 | * documentation and/or other materials provided with the distribution. |
| 14 | * |
| 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
| 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| 17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| 18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| 20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 25 | * |
| 26 | */ |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 27 | #include "includes.h" |
Damien Miller | d783435 | 2006-08-05 12:39:39 +1000 | [diff] [blame] | 28 | |
| 29 | #include "xmalloc.h" |
Damien Miller | 120a1ec | 2018-07-10 19:39:52 +1000 | [diff] [blame] | 30 | #include "sshbuf.h" |
| 31 | #include "ssherr.h" |
markus@openbsd.org | 5467fbc | 2018-07-11 18:53:29 +0000 | [diff] [blame] | 32 | #include "sshkey.h" |
Damien Miller | d783435 | 2006-08-05 12:39:39 +1000 | [diff] [blame] | 33 | #include "hostfile.h" |
Darren Tucker | cfea206 | 2004-02-10 15:27:34 +1100 | [diff] [blame] | 34 | #include "auth.h" |
Darren Tucker | 97363a8 | 2003-05-02 23:42:25 +1000 | [diff] [blame] | 35 | #include "ssh.h" |
Darren Tucker | 6b5a17b | 2018-03-26 13:12:44 +1100 | [diff] [blame] | 36 | #include "ssh_api.h" |
Darren Tucker | 97363a8 | 2003-05-02 23:42:25 +1000 | [diff] [blame] | 37 | #include "log.h" |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 38 | |
| 39 | #ifdef _AIX |
| 40 | |
Darren Tucker | 2eaea99 | 2006-07-12 23:41:33 +1000 | [diff] [blame] | 41 | #include <errno.h> |
Damien Miller | be43ebf | 2006-07-24 13:51:51 +1000 | [diff] [blame] | 42 | #if defined(HAVE_NETDB_H) |
| 43 | # include <netdb.h> |
| 44 | #endif |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 45 | #include <uinfo.h> |
Damien Miller | ded319c | 2006-09-01 15:38:36 +1000 | [diff] [blame] | 46 | #include <stdarg.h> |
Damien Miller | 62da44f | 2006-07-24 15:08:35 +1000 | [diff] [blame] | 47 | #include <string.h> |
| 48 | #include <unistd.h> |
Darren Tucker | 691d523 | 2005-02-15 21:45:57 +1100 | [diff] [blame] | 49 | #include <sys/socket.h> |
Darren Tucker | c70ce7b | 2006-09-18 23:54:32 +1000 | [diff] [blame] | 50 | |
| 51 | #ifdef WITH_AIXAUTHENTICATE |
| 52 | # include <login.h> |
| 53 | # include <userpw.h> |
| 54 | # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG) |
| 55 | # include <sys/audit.h> |
| 56 | # endif |
| 57 | # include <usersec.h> |
| 58 | #endif |
| 59 | |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 60 | #include "port-aix.h" |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 61 | |
Darren Tucker | b5d5ee1 | 2009-08-17 09:40:00 +1000 | [diff] [blame] | 62 | static char *lastlogin_msg = NULL; |
| 63 | |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 64 | # ifdef HAVE_SETAUTHDB |
| 65 | static char old_registry[REGISTRY_SIZE] = ""; |
| 66 | # endif |
| 67 | |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 68 | /* |
Darren Tucker | 6b2fe31 | 2005-05-29 10:32:47 +1000 | [diff] [blame] | 69 | * AIX has a "usrinfo" area where logname and other stuff is stored - |
Ben Lindstrom | 51b2488 | 2002-07-04 03:08:40 +0000 | [diff] [blame] | 70 | * a few applications actually use this and die if it's not set |
| 71 | * |
| 72 | * NOTE: TTY= should be set, but since no one uses it and it's hard to |
| 73 | * acquire due to privsep code. We will just drop support. |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 74 | */ |
| 75 | void |
Ben Lindstrom | 51b2488 | 2002-07-04 03:08:40 +0000 | [diff] [blame] | 76 | aix_usrinfo(struct passwd *pw) |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 77 | { |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 78 | u_int i; |
Damien Miller | 3174125 | 2003-05-19 00:13:38 +1000 | [diff] [blame] | 79 | size_t len; |
Ben Lindstrom | 51b2488 | 2002-07-04 03:08:40 +0000 | [diff] [blame] | 80 | char *cp; |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 81 | |
Damien Miller | 3174125 | 2003-05-19 00:13:38 +1000 | [diff] [blame] | 82 | len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name)); |
| 83 | cp = xmalloc(len); |
| 84 | |
Darren Tucker | 6b2fe31 | 2005-05-29 10:32:47 +1000 | [diff] [blame] | 85 | i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0', |
Damien Miller | 3867bf3 | 2003-05-19 09:33:15 +1000 | [diff] [blame] | 86 | pw->pw_name, '\0'); |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 87 | if (usrinfo(SETUINFO, cp, i) == -1) |
| 88 | fatal("Couldn't set usrinfo: %s", strerror(errno)); |
| 89 | debug3("AIX/UsrInfo: set len %d", i); |
Damien Miller | 3174125 | 2003-05-19 00:13:38 +1000 | [diff] [blame] | 90 | |
Darren Tucker | f60845f | 2013-06-02 08:07:31 +1000 | [diff] [blame] | 91 | free(cp); |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 92 | } |
| 93 | |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 94 | # ifdef WITH_AIXAUTHENTICATE |
Darren Tucker | b9aa0a0 | 2003-07-08 22:59:59 +1000 | [diff] [blame] | 95 | /* |
| 96 | * Remove embedded newlines in string (if any). |
| 97 | * Used before logging messages returned by AIX authentication functions |
| 98 | * so the message is logged on one line. |
| 99 | */ |
| 100 | void |
| 101 | aix_remove_embedded_newlines(char *p) |
| 102 | { |
| 103 | if (p == NULL) |
| 104 | return; |
| 105 | |
| 106 | for (; *p; p++) { |
| 107 | if (*p == '\n') |
| 108 | *p = ' '; |
| 109 | } |
| 110 | /* Remove trailing whitespace */ |
| 111 | if (*--p == ' ') |
| 112 | *p = '\0'; |
| 113 | } |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 114 | |
| 115 | /* |
Darren Tucker | 5a88d00 | 2004-08-29 21:43:33 +1000 | [diff] [blame] | 116 | * Test specifically for the case where SYSTEM == NONE and AUTH1 contains |
| 117 | * anything other than NONE or SYSTEM, which indicates that the admin has |
| 118 | * configured the account for purely AUTH1-type authentication. |
| 119 | * |
| 120 | * Since authenticate() doesn't check AUTH1, and sshd can't sanely support |
| 121 | * AUTH1 itself, in such a case authenticate() will allow access without |
| 122 | * authentation, which is almost certainly not what the admin intends. |
| 123 | * |
| 124 | * (The native tools, eg login, will process the AUTH1 list in addition to |
| 125 | * the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods |
| 126 | * have been deprecated since AIX 4.2.x and would be very difficult for sshd |
| 127 | * to support. |
| 128 | * |
| 129 | * Returns 0 if an unsupportable combination is found, 1 otherwise. |
| 130 | */ |
| 131 | static int |
| 132 | aix_valid_authentications(const char *user) |
| 133 | { |
| 134 | char *auth1, *sys, *p; |
| 135 | int valid = 1; |
| 136 | |
| 137 | if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) { |
| 138 | logit("Can't retrieve attribute SYSTEM for %s: %.100s", |
| 139 | user, strerror(errno)); |
| 140 | return 0; |
| 141 | } |
| 142 | |
| 143 | debug3("AIX SYSTEM attribute %s", sys); |
| 144 | if (strcmp(sys, "NONE") != 0) |
| 145 | return 1; /* not "NONE", so is OK */ |
| 146 | |
| 147 | if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) { |
| 148 | logit("Can't retrieve attribute auth1 for %s: %.100s", |
| 149 | user, strerror(errno)); |
| 150 | return 0; |
| 151 | } |
| 152 | |
| 153 | p = auth1; |
| 154 | /* A SEC_LIST is concatenated strings, ending with two NULs. */ |
| 155 | while (p[0] != '\0' && p[1] != '\0') { |
| 156 | debug3("AIX auth1 attribute list member %s", p); |
| 157 | if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) { |
| 158 | logit("Account %s has unsupported auth1 value '%s'", |
| 159 | user, p); |
| 160 | valid = 0; |
| 161 | } |
| 162 | p += strlen(p) + 1; |
| 163 | } |
| 164 | |
| 165 | return (valid); |
| 166 | } |
| 167 | |
| 168 | /* |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 169 | * Do authentication via AIX's authenticate routine. We loop until the |
| 170 | * reenter parameter is 0, but normally authenticate is called only once. |
| 171 | * |
| 172 | * Note: this function returns 1 on success, whereas AIX's authenticate() |
| 173 | * returns 0. |
| 174 | */ |
| 175 | int |
Tim Rice | bba02a5 | 2018-03-25 09:17:33 -0700 | [diff] [blame] | 176 | sys_auth_passwd(struct ssh *ssh, const char *password) |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 177 | { |
Tim Rice | bba02a5 | 2018-03-25 09:17:33 -0700 | [diff] [blame] | 178 | Authctxt *ctxt = ssh->authctxt; |
Darren Tucker | 782727a | 2005-05-29 10:28:48 +1000 | [diff] [blame] | 179 | char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name; |
Damien Miller | 120a1ec | 2018-07-10 19:39:52 +1000 | [diff] [blame] | 180 | int r, authsuccess = 0, expired, reenter, result; |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 181 | |
| 182 | do { |
| 183 | result = authenticate((char *)name, (char *)password, &reenter, |
| 184 | &authmsg); |
Darren Tucker | c20dccb | 2016-08-02 09:44:25 +1000 | [diff] [blame] | 185 | aix_remove_embedded_newlines(authmsg); |
Darren Tucker | f9fea65 | 2005-05-29 10:54:27 +1000 | [diff] [blame] | 186 | debug3("AIX/authenticate result %d, authmsg %.100s", result, |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 187 | authmsg); |
| 188 | } while (reenter); |
| 189 | |
Darren Tucker | 5a88d00 | 2004-08-29 21:43:33 +1000 | [diff] [blame] | 190 | if (!aix_valid_authentications(name)) |
| 191 | result = -1; |
| 192 | |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 193 | if (result == 0) { |
| 194 | authsuccess = 1; |
| 195 | |
Darren Tucker | 6b2fe31 | 2005-05-29 10:32:47 +1000 | [diff] [blame] | 196 | /* |
Darren Tucker | e3dba82 | 2004-02-10 12:50:19 +1100 | [diff] [blame] | 197 | * Record successful login. We don't have a pty yet, so just |
| 198 | * label the line as "ssh" |
| 199 | */ |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 200 | aix_setauthdb(name); |
Darren Tucker | e3dba82 | 2004-02-10 12:50:19 +1100 | [diff] [blame] | 201 | |
| 202 | /* |
| 203 | * Check if the user's password is expired. |
| 204 | */ |
Darren Tucker | a7ea546 | 2004-06-16 12:01:15 +1000 | [diff] [blame] | 205 | expired = passwdexpired(name, &msg); |
| 206 | if (msg && *msg) { |
Damien Miller | e36a5f6 | 2018-08-11 18:08:45 -0700 | [diff] [blame] | 207 | if ((r = sshbuf_put(ctxt->loginmsg, |
Damien Miller | 120a1ec | 2018-07-10 19:39:52 +1000 | [diff] [blame] | 208 | msg, strlen(msg))) != 0) |
| 209 | fatal("%s: buffer error: %s", |
| 210 | __func__, ssh_err(r)); |
Darren Tucker | a7ea546 | 2004-06-16 12:01:15 +1000 | [diff] [blame] | 211 | aix_remove_embedded_newlines(msg); |
| 212 | } |
| 213 | debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg); |
Darren Tucker | e3dba82 | 2004-02-10 12:50:19 +1100 | [diff] [blame] | 214 | |
| 215 | switch (expired) { |
| 216 | case 0: /* password not expired */ |
| 217 | break; |
| 218 | case 1: /* expired, password change required */ |
| 219 | ctxt->force_pwchange = 1; |
Darren Tucker | e3dba82 | 2004-02-10 12:50:19 +1100 | [diff] [blame] | 220 | break; |
| 221 | default: /* user can't change(2) or other error (-1) */ |
| 222 | logit("Password can't be changed for user %s: %.100s", |
| 223 | name, msg); |
Darren Tucker | f60845f | 2013-06-02 08:07:31 +1000 | [diff] [blame] | 224 | free(msg); |
Darren Tucker | e3dba82 | 2004-02-10 12:50:19 +1100 | [diff] [blame] | 225 | authsuccess = 0; |
| 226 | } |
| 227 | |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 228 | aix_restoreauthdb(); |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 229 | } |
| 230 | |
Darren Tucker | f60845f | 2013-06-02 08:07:31 +1000 | [diff] [blame] | 231 | free(authmsg); |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 232 | |
| 233 | return authsuccess; |
| 234 | } |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 235 | |
| 236 | /* |
| 237 | * Check if specified account is permitted to log in. |
| 238 | * Returns 1 if login is allowed, 0 if not allowed. |
| 239 | */ |
| 240 | int |
Damien Miller | 120a1ec | 2018-07-10 19:39:52 +1000 | [diff] [blame] | 241 | sys_auth_allowed_user(struct passwd *pw, struct sshbuf *loginmsg) |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 242 | { |
| 243 | char *msg = NULL; |
Damien Miller | e36a5f6 | 2018-08-11 18:08:45 -0700 | [diff] [blame] | 244 | int r, result, permitted = 0; |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 245 | struct stat st; |
| 246 | |
| 247 | /* |
| 248 | * Don't perform checks for root account (PermitRootLogin controls |
Darren Tucker | 863cfa0 | 2007-08-09 14:29:47 +1000 | [diff] [blame] | 249 | * logins via ssh) or if running as non-root user (since |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 250 | * loginrestrictions will always fail due to insufficient privilege). |
| 251 | */ |
| 252 | if (pw->pw_uid == 0 || geteuid() != 0) { |
Darren Tucker | 5288cb2 | 2004-06-28 18:11:19 +1000 | [diff] [blame] | 253 | debug3("%s: not checking", __func__); |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 254 | return 1; |
| 255 | } |
| 256 | |
| 257 | result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg); |
| 258 | if (result == 0) |
| 259 | permitted = 1; |
| 260 | /* |
| 261 | * If restricted because /etc/nologin exists, the login will be denied |
| 262 | * in session.c after the nologin message is sent, so allow for now |
| 263 | * and do not append the returned message. |
| 264 | */ |
| 265 | if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0) |
| 266 | permitted = 1; |
Damien Miller | 120a1ec | 2018-07-10 19:39:52 +1000 | [diff] [blame] | 267 | else if (msg != NULL) { |
| 268 | if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0) |
| 269 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
Damien Miller | e36a5f6 | 2018-08-11 18:08:45 -0700 | [diff] [blame] | 270 | } |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 271 | if (msg == NULL) |
| 272 | msg = xstrdup("(none)"); |
| 273 | aix_remove_embedded_newlines(msg); |
| 274 | debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg); |
| 275 | |
| 276 | if (!permitted) |
| 277 | logit("Login restricted for %s: %.100s", pw->pw_name, msg); |
Darren Tucker | f60845f | 2013-06-02 08:07:31 +1000 | [diff] [blame] | 278 | free(msg); |
Darren Tucker | 0a9d43d | 2004-06-23 13:45:24 +1000 | [diff] [blame] | 279 | return permitted; |
| 280 | } |
| 281 | |
Darren Tucker | 397a2f2 | 2004-08-15 00:09:11 +1000 | [diff] [blame] | 282 | int |
Damien Miller | 08f66d9 | 2019-01-20 09:58:45 +1100 | [diff] [blame] | 283 | sys_auth_record_login(struct ssh *ssh, const char *user, const char *host, |
| 284 | const char *ttynm, struct sshbuf *loginmsg) |
Darren Tucker | 397a2f2 | 2004-08-15 00:09:11 +1000 | [diff] [blame] | 285 | { |
Darren Tucker | 782727a | 2005-05-29 10:28:48 +1000 | [diff] [blame] | 286 | char *msg = NULL; |
Darren Tucker | 397a2f2 | 2004-08-15 00:09:11 +1000 | [diff] [blame] | 287 | int success = 0; |
| 288 | |
| 289 | aix_setauthdb(user); |
Darren Tucker | b4d3012 | 2005-02-08 21:06:55 +1100 | [diff] [blame] | 290 | if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) { |
Darren Tucker | 397a2f2 | 2004-08-15 00:09:11 +1000 | [diff] [blame] | 291 | success = 1; |
Darren Tucker | b5d5ee1 | 2009-08-17 09:40:00 +1000 | [diff] [blame] | 292 | if (msg != NULL) { |
Darren Tucker | b4d3012 | 2005-02-08 21:06:55 +1100 | [diff] [blame] | 293 | debug("AIX/loginsuccess: msg %s", msg); |
Darren Tucker | b5d5ee1 | 2009-08-17 09:40:00 +1000 | [diff] [blame] | 294 | if (lastlogin_msg == NULL) |
| 295 | lastlogin_msg = msg; |
Darren Tucker | 397a2f2 | 2004-08-15 00:09:11 +1000 | [diff] [blame] | 296 | } |
| 297 | } |
| 298 | aix_restoreauthdb(); |
| 299 | return (success); |
| 300 | } |
| 301 | |
Darren Tucker | b5d5ee1 | 2009-08-17 09:40:00 +1000 | [diff] [blame] | 302 | char * |
| 303 | sys_auth_get_lastlogin_msg(const char *user, uid_t uid) |
| 304 | { |
| 305 | char *msg = lastlogin_msg; |
| 306 | |
| 307 | lastlogin_msg = NULL; |
| 308 | return msg; |
| 309 | } |
| 310 | |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 311 | # ifdef CUSTOM_FAILED_LOGIN |
Darren Tucker | 97363a8 | 2003-05-02 23:42:25 +1000 | [diff] [blame] | 312 | /* |
| 313 | * record_failed_login: generic "login failed" interface function |
| 314 | */ |
| 315 | void |
Darren Tucker | 42d9dc7 | 2005-02-02 17:10:11 +1100 | [diff] [blame] | 316 | record_failed_login(const char *user, const char *hostname, const char *ttyname) |
Darren Tucker | 97363a8 | 2003-05-02 23:42:25 +1000 | [diff] [blame] | 317 | { |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 318 | if (geteuid() != 0) |
| 319 | return; |
| 320 | |
| 321 | aix_setauthdb(user); |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 322 | # ifdef AIX_LOGINFAILED_4ARG |
Darren Tucker | b4d3012 | 2005-02-08 21:06:55 +1100 | [diff] [blame] | 323 | loginfailed((char *)user, (char *)hostname, (char *)ttyname, |
| 324 | AUDIT_FAIL_AUTH); |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 325 | # else |
Darren Tucker | b4d3012 | 2005-02-08 21:06:55 +1100 | [diff] [blame] | 326 | loginfailed((char *)user, (char *)hostname, (char *)ttyname); |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 327 | # endif |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 328 | aix_restoreauthdb(); |
Darren Tucker | 97363a8 | 2003-05-02 23:42:25 +1000 | [diff] [blame] | 329 | } |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 330 | # endif /* CUSTOM_FAILED_LOGIN */ |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 331 | |
| 332 | /* |
| 333 | * If we have setauthdb, retrieve the password registry for the user's |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 334 | * account then feed it to setauthdb. This will mean that subsequent AIX auth |
| 335 | * functions will only use the specified loadable module. If we don't have |
| 336 | * setauthdb this is a no-op. |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 337 | */ |
| 338 | void |
| 339 | aix_setauthdb(const char *user) |
| 340 | { |
| 341 | # ifdef HAVE_SETAUTHDB |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 342 | char *registry; |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 343 | |
| 344 | if (setuserdb(S_READ) == -1) { |
| 345 | debug3("%s: Could not open userdb to read", __func__); |
| 346 | return; |
| 347 | } |
Darren Tucker | c20dccb | 2016-08-02 09:44:25 +1000 | [diff] [blame] | 348 | |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 349 | if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) { |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 350 | if (setauthdb(registry, old_registry) == 0) |
| 351 | debug3("AIX/setauthdb set registry '%s'", registry); |
Darren Tucker | c20dccb | 2016-08-02 09:44:25 +1000 | [diff] [blame] | 352 | else |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 353 | debug3("AIX/setauthdb set registry '%s' failed: %s", |
| 354 | registry, strerror(errno)); |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 355 | } else |
| 356 | debug3("%s: Could not read S_REGISTRY for user: %s", __func__, |
| 357 | strerror(errno)); |
| 358 | enduserdb(); |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 359 | # endif /* HAVE_SETAUTHDB */ |
Darren Tucker | fc3454e | 2003-07-14 16:41:55 +1000 | [diff] [blame] | 360 | } |
Ben Lindstrom | a9c039c | 2002-02-19 20:27:55 +0000 | [diff] [blame] | 361 | |
Darren Tucker | e45674a | 2004-02-06 16:17:51 +1100 | [diff] [blame] | 362 | /* |
| 363 | * Restore the user's registry settings from old_registry. |
| 364 | * Note that if the first aix_setauthdb fails, setauthdb("") is still safe |
| 365 | * (it restores the system default behaviour). If we don't have setauthdb, |
| 366 | * this is a no-op. |
| 367 | */ |
| 368 | void |
| 369 | aix_restoreauthdb(void) |
| 370 | { |
| 371 | # ifdef HAVE_SETAUTHDB |
| 372 | if (setauthdb(old_registry, NULL) == 0) |
| 373 | debug3("%s: restoring old registry '%s'", __func__, |
| 374 | old_registry); |
| 375 | else |
| 376 | debug3("%s: failed to restore old registry %s", __func__, |
| 377 | old_registry); |
| 378 | # endif /* HAVE_SETAUTHDB */ |
| 379 | } |
| 380 | |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 381 | # endif /* WITH_AIXAUTHENTICATE */ |
| 382 | |
Darren Tucker | 1bf3503 | 2009-12-21 10:49:21 +1100 | [diff] [blame] | 383 | # ifdef USE_AIX_KRB_NAME |
| 384 | /* |
| 385 | * aix_krb5_get_principal_name: returns the user's kerberos client principal name if |
| 386 | * configured, otherwise NULL. Caller must free returned string. |
| 387 | */ |
| 388 | char * |
| 389 | aix_krb5_get_principal_name(char *pw_name) |
| 390 | { |
| 391 | char *authname = NULL, *authdomain = NULL, *principal = NULL; |
| 392 | |
| 393 | setuserdb(S_READ); |
| 394 | if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0) |
| 395 | debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno)); |
| 396 | if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0) |
| 397 | debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno)); |
| 398 | |
| 399 | if (authdomain != NULL) |
| 400 | xasprintf(&principal, "%s@%s", authname ? authname : pw_name, authdomain); |
| 401 | else if (authname != NULL) |
| 402 | principal = xstrdup(authname); |
| 403 | enduserdb(); |
| 404 | return principal; |
| 405 | } |
| 406 | # endif /* USE_AIX_KRB_NAME */ |
| 407 | |
Darren Tucker | 691d523 | 2005-02-15 21:45:57 +1100 | [diff] [blame] | 408 | # if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO) |
| 409 | # undef getnameinfo |
| 410 | /* |
| 411 | * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros |
| 412 | * IPv6 address into its textual representation ("::"), so we wrap it |
| 413 | * with a function that will. |
| 414 | */ |
| 415 | int |
| 416 | sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host, |
| 417 | size_t hostlen, char *serv, size_t servlen, int flags) |
| 418 | { |
| 419 | struct sockaddr_in6 *sa6; |
| 420 | u_int32_t *a6; |
| 421 | |
| 422 | if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) && |
| 423 | sa->sa_family == AF_INET6) { |
| 424 | sa6 = (struct sockaddr_in6 *)sa; |
| 425 | a6 = sa6->sin6_addr.u6_addr.u6_addr32; |
| 426 | |
| 427 | if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) { |
| 428 | strlcpy(host, "::", hostlen); |
| 429 | snprintf(serv, servlen, "%d", sa6->sin6_port); |
| 430 | return 0; |
| 431 | } |
| 432 | } |
| 433 | return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags); |
| 434 | } |
| 435 | # endif /* AIX_GETNAMEINFO_HACK */ |
| 436 | |
Darren Tucker | 0f26b13 | 2008-02-28 23:16:04 +1100 | [diff] [blame] | 437 | # if defined(USE_GETGRSET) |
| 438 | # include <stdlib.h> |
| 439 | int |
| 440 | getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt) |
| 441 | { |
| 442 | char *cp, *grplist, *grp; |
| 443 | gid_t gid; |
| 444 | int ret = 0, ngroups = 0, maxgroups; |
| 445 | long l; |
| 446 | |
| 447 | maxgroups = *grpcnt; |
| 448 | |
| 449 | if ((cp = grplist = getgrset(user)) == NULL) |
| 450 | return -1; |
| 451 | |
| 452 | /* handle zero-length case */ |
| 453 | if (maxgroups <= 0) { |
| 454 | *grpcnt = 0; |
| 455 | return -1; |
| 456 | } |
| 457 | |
| 458 | /* copy primary group */ |
| 459 | groups[ngroups++] = pgid; |
| 460 | |
| 461 | /* copy each entry from getgrset into group list */ |
| 462 | while ((grp = strsep(&grplist, ",")) != NULL) { |
| 463 | l = strtol(grp, NULL, 10); |
| 464 | if (ngroups >= maxgroups || l == LONG_MIN || l == LONG_MAX) { |
| 465 | ret = -1; |
| 466 | goto out; |
| 467 | } |
| 468 | gid = (gid_t)l; |
| 469 | if (gid == pgid) |
| 470 | continue; /* we have already added primary gid */ |
| 471 | groups[ngroups++] = gid; |
| 472 | } |
| 473 | out: |
| 474 | free(cp); |
| 475 | *grpcnt = ngroups; |
| 476 | return ret; |
| 477 | } |
Darren Tucker | 0f26b13 | 2008-02-28 23:16:04 +1100 | [diff] [blame] | 478 | # endif /* USE_GETGRSET */ |
| 479 | |
Darren Tucker | d763416 | 2003-11-22 14:16:56 +1100 | [diff] [blame] | 480 | #endif /* _AIX */ |