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