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
29*19261079SEd Maste #ifdef _AIX
30*19261079SEd Maste
31761efaa7SDag-Erling Smørgrav #include "xmalloc.h"
32190cef3dSDag-Erling Smørgrav #include "sshbuf.h"
33190cef3dSDag-Erling Smørgrav #include "ssherr.h"
34190cef3dSDag-Erling Smørgrav #include "sshkey.h"
35761efaa7SDag-Erling Smørgrav #include "hostfile.h"
36efcad6b7SDag-Erling Smørgrav #include "auth.h"
37d95e11bfSDag-Erling Smørgrav #include "ssh.h"
3847dd1d1bSDag-Erling Smørgrav #include "ssh_api.h"
39d95e11bfSDag-Erling Smørgrav #include "log.h"
4083d2307dSDag-Erling Smørgrav
41761efaa7SDag-Erling Smørgrav #include <errno.h>
42761efaa7SDag-Erling Smørgrav #if defined(HAVE_NETDB_H)
43761efaa7SDag-Erling Smørgrav # include <netdb.h>
44761efaa7SDag-Erling Smørgrav #endif
4583d2307dSDag-Erling Smørgrav #include <uinfo.h>
46761efaa7SDag-Erling Smørgrav #include <stdarg.h>
47761efaa7SDag-Erling Smørgrav #include <string.h>
48761efaa7SDag-Erling Smørgrav #include <unistd.h>
495e8dbd04SDag-Erling Smørgrav #include <sys/socket.h>
50761efaa7SDag-Erling Smørgrav
51761efaa7SDag-Erling Smørgrav #ifdef WITH_AIXAUTHENTICATE
52761efaa7SDag-Erling Smørgrav # include <login.h>
53761efaa7SDag-Erling Smørgrav # include <userpw.h>
54761efaa7SDag-Erling Smørgrav # if defined(HAVE_SYS_AUDIT_H) && defined(AIX_LOGINFAILED_4ARG)
55761efaa7SDag-Erling Smørgrav # include <sys/audit.h>
56761efaa7SDag-Erling Smørgrav # endif
57761efaa7SDag-Erling Smørgrav # include <usersec.h>
58761efaa7SDag-Erling Smørgrav #endif
59761efaa7SDag-Erling Smørgrav
60d95e11bfSDag-Erling Smørgrav #include "port-aix.h"
61d95e11bfSDag-Erling Smørgrav
627aee6ffeSDag-Erling Smørgrav static char *lastlogin_msg = NULL;
637aee6ffeSDag-Erling Smørgrav
64efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB
65efcad6b7SDag-Erling Smørgrav static char old_registry[REGISTRY_SIZE] = "";
66efcad6b7SDag-Erling Smørgrav # endif
6783d2307dSDag-Erling Smørgrav
6883d2307dSDag-Erling Smørgrav /*
694b17dab0SDag-Erling Smørgrav * AIX has a "usrinfo" area where logname and other stuff is stored -
704b17dab0SDag-Erling Smørgrav * a few applications actually use this and die if it's not set
714b17dab0SDag-Erling Smørgrav *
724b17dab0SDag-Erling Smørgrav * NOTE: TTY= should be set, but since no one uses it and it's hard to
734b17dab0SDag-Erling Smørgrav * acquire due to privsep code. We will just drop support.
7483d2307dSDag-Erling Smørgrav */
7583d2307dSDag-Erling Smørgrav void
aix_usrinfo(struct passwd * pw)764b17dab0SDag-Erling Smørgrav aix_usrinfo(struct passwd *pw)
7783d2307dSDag-Erling Smørgrav {
7883d2307dSDag-Erling Smørgrav u_int i;
79d95e11bfSDag-Erling Smørgrav size_t len;
804b17dab0SDag-Erling Smørgrav char *cp;
8183d2307dSDag-Erling Smørgrav
82d95e11bfSDag-Erling Smørgrav len = sizeof("LOGNAME= NAME= ") + (2 * strlen(pw->pw_name));
83d95e11bfSDag-Erling Smørgrav cp = xmalloc(len);
84d95e11bfSDag-Erling Smørgrav
85d95e11bfSDag-Erling Smørgrav i = snprintf(cp, len, "LOGNAME=%s%cNAME=%s%c", pw->pw_name, '\0',
86d95e11bfSDag-Erling Smørgrav pw->pw_name, '\0');
8783d2307dSDag-Erling Smørgrav if (usrinfo(SETUINFO, cp, i) == -1)
8883d2307dSDag-Erling Smørgrav fatal("Couldn't set usrinfo: %s", strerror(errno));
8983d2307dSDag-Erling Smørgrav debug3("AIX/UsrInfo: set len %d", i);
90d95e11bfSDag-Erling Smørgrav
91e4a9863fSDag-Erling Smørgrav free(cp);
9283d2307dSDag-Erling Smørgrav }
9383d2307dSDag-Erling Smørgrav
94d95e11bfSDag-Erling Smørgrav # ifdef WITH_AIXAUTHENTICATE
95d95e11bfSDag-Erling Smørgrav /*
96d95e11bfSDag-Erling Smørgrav * Remove embedded newlines in string (if any).
97d95e11bfSDag-Erling Smørgrav * Used before logging messages returned by AIX authentication functions
98d95e11bfSDag-Erling Smørgrav * so the message is logged on one line.
99d95e11bfSDag-Erling Smørgrav */
100d95e11bfSDag-Erling Smørgrav void
aix_remove_embedded_newlines(char * p)101d95e11bfSDag-Erling Smørgrav aix_remove_embedded_newlines(char *p)
102d95e11bfSDag-Erling Smørgrav {
103d95e11bfSDag-Erling Smørgrav if (p == NULL)
104d95e11bfSDag-Erling Smørgrav return;
105d95e11bfSDag-Erling Smørgrav
106d95e11bfSDag-Erling Smørgrav for (; *p; p++) {
107d95e11bfSDag-Erling Smørgrav if (*p == '\n')
108d95e11bfSDag-Erling Smørgrav *p = ' ';
109d95e11bfSDag-Erling Smørgrav }
110d95e11bfSDag-Erling Smørgrav /* Remove trailing whitespace */
111d95e11bfSDag-Erling Smørgrav if (*--p == ' ')
112d95e11bfSDag-Erling Smørgrav *p = '\0';
113d95e11bfSDag-Erling Smørgrav }
114efcad6b7SDag-Erling Smørgrav
115efcad6b7SDag-Erling Smørgrav /*
1165e8dbd04SDag-Erling Smørgrav * Test specifically for the case where SYSTEM == NONE and AUTH1 contains
1175e8dbd04SDag-Erling Smørgrav * anything other than NONE or SYSTEM, which indicates that the admin has
1185e8dbd04SDag-Erling Smørgrav * configured the account for purely AUTH1-type authentication.
1195e8dbd04SDag-Erling Smørgrav *
1205e8dbd04SDag-Erling Smørgrav * Since authenticate() doesn't check AUTH1, and sshd can't sanely support
1215e8dbd04SDag-Erling Smørgrav * AUTH1 itself, in such a case authenticate() will allow access without
1225e8dbd04SDag-Erling Smørgrav * authentation, which is almost certainly not what the admin intends.
1235e8dbd04SDag-Erling Smørgrav *
1245e8dbd04SDag-Erling Smørgrav * (The native tools, eg login, will process the AUTH1 list in addition to
1255e8dbd04SDag-Erling Smørgrav * the SYSTEM list by using ckuserID(), however ckuserID() and AUTH1 methods
1265e8dbd04SDag-Erling Smørgrav * have been deprecated since AIX 4.2.x and would be very difficult for sshd
1275e8dbd04SDag-Erling Smørgrav * to support.
1285e8dbd04SDag-Erling Smørgrav *
1295e8dbd04SDag-Erling Smørgrav * Returns 0 if an unsupportable combination is found, 1 otherwise.
1305e8dbd04SDag-Erling Smørgrav */
1315e8dbd04SDag-Erling Smørgrav static int
aix_valid_authentications(const char * user)1325e8dbd04SDag-Erling Smørgrav aix_valid_authentications(const char *user)
1335e8dbd04SDag-Erling Smørgrav {
1345e8dbd04SDag-Erling Smørgrav char *auth1, *sys, *p;
1355e8dbd04SDag-Erling Smørgrav int valid = 1;
1365e8dbd04SDag-Erling Smørgrav
1375e8dbd04SDag-Erling Smørgrav if (getuserattr((char *)user, S_AUTHSYSTEM, &sys, SEC_CHAR) != 0) {
1385e8dbd04SDag-Erling Smørgrav logit("Can't retrieve attribute SYSTEM for %s: %.100s",
1395e8dbd04SDag-Erling Smørgrav user, strerror(errno));
1405e8dbd04SDag-Erling Smørgrav return 0;
1415e8dbd04SDag-Erling Smørgrav }
1425e8dbd04SDag-Erling Smørgrav
1435e8dbd04SDag-Erling Smørgrav debug3("AIX SYSTEM attribute %s", sys);
1445e8dbd04SDag-Erling Smørgrav if (strcmp(sys, "NONE") != 0)
1455e8dbd04SDag-Erling Smørgrav return 1; /* not "NONE", so is OK */
1465e8dbd04SDag-Erling Smørgrav
1475e8dbd04SDag-Erling Smørgrav if (getuserattr((char *)user, S_AUTH1, &auth1, SEC_LIST) != 0) {
1485e8dbd04SDag-Erling Smørgrav logit("Can't retrieve attribute auth1 for %s: %.100s",
1495e8dbd04SDag-Erling Smørgrav user, strerror(errno));
1505e8dbd04SDag-Erling Smørgrav return 0;
1515e8dbd04SDag-Erling Smørgrav }
1525e8dbd04SDag-Erling Smørgrav
1535e8dbd04SDag-Erling Smørgrav p = auth1;
1545e8dbd04SDag-Erling Smørgrav /* A SEC_LIST is concatenated strings, ending with two NULs. */
1555e8dbd04SDag-Erling Smørgrav while (p[0] != '\0' && p[1] != '\0') {
1565e8dbd04SDag-Erling Smørgrav debug3("AIX auth1 attribute list member %s", p);
1575e8dbd04SDag-Erling Smørgrav if (strcmp(p, "NONE") != 0 && strcmp(p, "SYSTEM")) {
1585e8dbd04SDag-Erling Smørgrav logit("Account %s has unsupported auth1 value '%s'",
1595e8dbd04SDag-Erling Smørgrav user, p);
1605e8dbd04SDag-Erling Smørgrav valid = 0;
1615e8dbd04SDag-Erling Smørgrav }
1625e8dbd04SDag-Erling Smørgrav p += strlen(p) + 1;
1635e8dbd04SDag-Erling Smørgrav }
1645e8dbd04SDag-Erling Smørgrav
1655e8dbd04SDag-Erling Smørgrav return (valid);
1665e8dbd04SDag-Erling Smørgrav }
1675e8dbd04SDag-Erling Smørgrav
1685e8dbd04SDag-Erling Smørgrav /*
169efcad6b7SDag-Erling Smørgrav * Do authentication via AIX's authenticate routine. We loop until the
170efcad6b7SDag-Erling Smørgrav * reenter parameter is 0, but normally authenticate is called only once.
171efcad6b7SDag-Erling Smørgrav *
172efcad6b7SDag-Erling Smørgrav * Note: this function returns 1 on success, whereas AIX's authenticate()
173efcad6b7SDag-Erling Smørgrav * returns 0.
174efcad6b7SDag-Erling Smørgrav */
175efcad6b7SDag-Erling Smørgrav int
sys_auth_passwd(struct ssh * ssh,const char * password)17647dd1d1bSDag-Erling Smørgrav sys_auth_passwd(struct ssh *ssh, const char *password)
177efcad6b7SDag-Erling Smørgrav {
17847dd1d1bSDag-Erling Smørgrav Authctxt *ctxt = ssh->authctxt;
179043840dfSDag-Erling Smørgrav char *authmsg = NULL, *msg = NULL, *name = ctxt->pw->pw_name;
180190cef3dSDag-Erling Smørgrav int r, authsuccess = 0, expired, reenter, result;
181efcad6b7SDag-Erling Smørgrav
182efcad6b7SDag-Erling Smørgrav do {
183efcad6b7SDag-Erling Smørgrav result = authenticate((char *)name, (char *)password, &reenter,
184efcad6b7SDag-Erling Smørgrav &authmsg);
185efcad6b7SDag-Erling Smørgrav aix_remove_embedded_newlines(authmsg);
186043840dfSDag-Erling Smørgrav debug3("AIX/authenticate result %d, authmsg %.100s", result,
187efcad6b7SDag-Erling Smørgrav authmsg);
188efcad6b7SDag-Erling Smørgrav } while (reenter);
189efcad6b7SDag-Erling Smørgrav
1905e8dbd04SDag-Erling Smørgrav if (!aix_valid_authentications(name))
1915e8dbd04SDag-Erling Smørgrav result = -1;
1925e8dbd04SDag-Erling Smørgrav
193efcad6b7SDag-Erling Smørgrav if (result == 0) {
194efcad6b7SDag-Erling Smørgrav authsuccess = 1;
195efcad6b7SDag-Erling Smørgrav
196efcad6b7SDag-Erling Smørgrav /*
197efcad6b7SDag-Erling Smørgrav * Record successful login. We don't have a pty yet, so just
198efcad6b7SDag-Erling Smørgrav * label the line as "ssh"
199efcad6b7SDag-Erling Smørgrav */
200efcad6b7SDag-Erling Smørgrav aix_setauthdb(name);
201efcad6b7SDag-Erling Smørgrav
202efcad6b7SDag-Erling Smørgrav /*
203efcad6b7SDag-Erling Smørgrav * Check if the user's password is expired.
204efcad6b7SDag-Erling Smørgrav */
205efcad6b7SDag-Erling Smørgrav expired = passwdexpired(name, &msg);
206efcad6b7SDag-Erling Smørgrav if (msg && *msg) {
207190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(ctxt->loginmsg,
208190cef3dSDag-Erling Smørgrav msg, strlen(msg))) != 0)
209190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s",
210190cef3dSDag-Erling Smørgrav __func__, ssh_err(r));
211efcad6b7SDag-Erling Smørgrav aix_remove_embedded_newlines(msg);
212efcad6b7SDag-Erling Smørgrav }
213efcad6b7SDag-Erling Smørgrav debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg);
214efcad6b7SDag-Erling Smørgrav
215efcad6b7SDag-Erling Smørgrav switch (expired) {
216efcad6b7SDag-Erling Smørgrav case 0: /* password not expired */
217efcad6b7SDag-Erling Smørgrav break;
218efcad6b7SDag-Erling Smørgrav case 1: /* expired, password change required */
219efcad6b7SDag-Erling Smørgrav ctxt->force_pwchange = 1;
220efcad6b7SDag-Erling Smørgrav break;
221efcad6b7SDag-Erling Smørgrav default: /* user can't change(2) or other error (-1) */
222efcad6b7SDag-Erling Smørgrav logit("Password can't be changed for user %s: %.100s",
223efcad6b7SDag-Erling Smørgrav name, msg);
224e4a9863fSDag-Erling Smørgrav free(msg);
225efcad6b7SDag-Erling Smørgrav authsuccess = 0;
226efcad6b7SDag-Erling Smørgrav }
227efcad6b7SDag-Erling Smørgrav
228efcad6b7SDag-Erling Smørgrav aix_restoreauthdb();
229efcad6b7SDag-Erling Smørgrav }
230efcad6b7SDag-Erling Smørgrav
231e4a9863fSDag-Erling Smørgrav free(authmsg);
232efcad6b7SDag-Erling Smørgrav
233efcad6b7SDag-Erling Smørgrav return authsuccess;
234efcad6b7SDag-Erling Smørgrav }
235d95e11bfSDag-Erling Smørgrav
236d74d50a8SDag-Erling Smørgrav /*
237d74d50a8SDag-Erling Smørgrav * Check if specified account is permitted to log in.
238d74d50a8SDag-Erling Smørgrav * Returns 1 if login is allowed, 0 if not allowed.
239d74d50a8SDag-Erling Smørgrav */
240d74d50a8SDag-Erling Smørgrav int
sys_auth_allowed_user(struct passwd * pw,struct sshbuf * loginmsg)241190cef3dSDag-Erling Smørgrav sys_auth_allowed_user(struct passwd *pw, struct sshbuf *loginmsg)
242d74d50a8SDag-Erling Smørgrav {
243d74d50a8SDag-Erling Smørgrav char *msg = NULL;
244190cef3dSDag-Erling Smørgrav int r, result, permitted = 0;
245d74d50a8SDag-Erling Smørgrav struct stat st;
246d74d50a8SDag-Erling Smørgrav
247d74d50a8SDag-Erling Smørgrav /*
248d74d50a8SDag-Erling Smørgrav * Don't perform checks for root account (PermitRootLogin controls
249d4af9e69SDag-Erling Smørgrav * logins via ssh) or if running as non-root user (since
250d74d50a8SDag-Erling Smørgrav * loginrestrictions will always fail due to insufficient privilege).
251d74d50a8SDag-Erling Smørgrav */
252d74d50a8SDag-Erling Smørgrav if (pw->pw_uid == 0 || geteuid() != 0) {
253d74d50a8SDag-Erling Smørgrav debug3("%s: not checking", __func__);
254d74d50a8SDag-Erling Smørgrav return 1;
255d74d50a8SDag-Erling Smørgrav }
256d74d50a8SDag-Erling Smørgrav
257d74d50a8SDag-Erling Smørgrav result = loginrestrictions(pw->pw_name, S_RLOGIN, NULL, &msg);
258d74d50a8SDag-Erling Smørgrav if (result == 0)
259d74d50a8SDag-Erling Smørgrav permitted = 1;
260d74d50a8SDag-Erling Smørgrav /*
261d74d50a8SDag-Erling Smørgrav * If restricted because /etc/nologin exists, the login will be denied
262d74d50a8SDag-Erling Smørgrav * in session.c after the nologin message is sent, so allow for now
263d74d50a8SDag-Erling Smørgrav * and do not append the returned message.
264d74d50a8SDag-Erling Smørgrav */
265d74d50a8SDag-Erling Smørgrav if (result == -1 && errno == EPERM && stat(_PATH_NOLOGIN, &st) == 0)
266d74d50a8SDag-Erling Smørgrav permitted = 1;
267190cef3dSDag-Erling Smørgrav else if (msg != NULL) {
268190cef3dSDag-Erling Smørgrav if ((r = sshbuf_put(loginmsg, msg, strlen(msg))) != 0)
269190cef3dSDag-Erling Smørgrav fatal("%s: buffer error: %s", __func__, ssh_err(r));
270190cef3dSDag-Erling Smørgrav }
271d74d50a8SDag-Erling Smørgrav if (msg == NULL)
272d74d50a8SDag-Erling Smørgrav msg = xstrdup("(none)");
273d74d50a8SDag-Erling Smørgrav aix_remove_embedded_newlines(msg);
274d74d50a8SDag-Erling Smørgrav debug3("AIX/loginrestrictions returned %d msg %.100s", result, msg);
275d74d50a8SDag-Erling Smørgrav
276d74d50a8SDag-Erling Smørgrav if (!permitted)
277d74d50a8SDag-Erling Smørgrav logit("Login restricted for %s: %.100s", pw->pw_name, msg);
278e4a9863fSDag-Erling Smørgrav free(msg);
279d74d50a8SDag-Erling Smørgrav return permitted;
280d74d50a8SDag-Erling Smørgrav }
281d74d50a8SDag-Erling Smørgrav
282d74d50a8SDag-Erling Smørgrav int
sys_auth_record_login(const char * user,const char * host,const char * ttynm,struct sshbuf * loginmsg)2835e8dbd04SDag-Erling Smørgrav sys_auth_record_login(const char *user, const char *host, const char *ttynm,
284190cef3dSDag-Erling Smørgrav struct sshbuf *loginmsg)
285d74d50a8SDag-Erling Smørgrav {
286043840dfSDag-Erling Smørgrav char *msg = NULL;
287d74d50a8SDag-Erling Smørgrav int success = 0;
288d74d50a8SDag-Erling Smørgrav
289d74d50a8SDag-Erling Smørgrav aix_setauthdb(user);
2905e8dbd04SDag-Erling Smørgrav if (loginsuccess((char *)user, (char *)host, (char *)ttynm, &msg) == 0) {
291d74d50a8SDag-Erling Smørgrav success = 1;
2927aee6ffeSDag-Erling Smørgrav if (msg != NULL) {
2935e8dbd04SDag-Erling Smørgrav debug("AIX/loginsuccess: msg %s", msg);
2947aee6ffeSDag-Erling Smørgrav if (lastlogin_msg == NULL)
2957aee6ffeSDag-Erling Smørgrav lastlogin_msg = msg;
296d74d50a8SDag-Erling Smørgrav }
297d74d50a8SDag-Erling Smørgrav }
298d74d50a8SDag-Erling Smørgrav aix_restoreauthdb();
299d74d50a8SDag-Erling Smørgrav return (success);
300d74d50a8SDag-Erling Smørgrav }
301d74d50a8SDag-Erling Smørgrav
3027aee6ffeSDag-Erling Smørgrav char *
sys_auth_get_lastlogin_msg(const char * user,uid_t uid)3037aee6ffeSDag-Erling Smørgrav sys_auth_get_lastlogin_msg(const char *user, uid_t uid)
3047aee6ffeSDag-Erling Smørgrav {
3057aee6ffeSDag-Erling Smørgrav char *msg = lastlogin_msg;
3067aee6ffeSDag-Erling Smørgrav
3077aee6ffeSDag-Erling Smørgrav lastlogin_msg = NULL;
3087aee6ffeSDag-Erling Smørgrav return msg;
3097aee6ffeSDag-Erling Smørgrav }
3107aee6ffeSDag-Erling Smørgrav
311d95e11bfSDag-Erling Smørgrav # ifdef CUSTOM_FAILED_LOGIN
312d95e11bfSDag-Erling Smørgrav /*
313d95e11bfSDag-Erling Smørgrav * record_failed_login: generic "login failed" interface function
314d95e11bfSDag-Erling Smørgrav */
315d95e11bfSDag-Erling Smørgrav void
record_failed_login(struct ssh * ssh,const char * user,const char * hostname,const char * ttyname)316*19261079SEd Maste record_failed_login(struct ssh *ssh, const char *user, const char *hostname,
317*19261079SEd Maste const char *ttyname)
318d95e11bfSDag-Erling Smørgrav {
319d95e11bfSDag-Erling Smørgrav if (geteuid() != 0)
320d95e11bfSDag-Erling Smørgrav return;
321d95e11bfSDag-Erling Smørgrav
322d95e11bfSDag-Erling Smørgrav aix_setauthdb(user);
323d95e11bfSDag-Erling Smørgrav # ifdef AIX_LOGINFAILED_4ARG
3245e8dbd04SDag-Erling Smørgrav loginfailed((char *)user, (char *)hostname, (char *)ttyname,
3255e8dbd04SDag-Erling Smørgrav AUDIT_FAIL_AUTH);
326d95e11bfSDag-Erling Smørgrav # else
3275e8dbd04SDag-Erling Smørgrav loginfailed((char *)user, (char *)hostname, (char *)ttyname);
328d95e11bfSDag-Erling Smørgrav # endif
329efcad6b7SDag-Erling Smørgrav aix_restoreauthdb();
330d95e11bfSDag-Erling Smørgrav }
331efcad6b7SDag-Erling Smørgrav # endif /* CUSTOM_FAILED_LOGIN */
332d95e11bfSDag-Erling Smørgrav
333d95e11bfSDag-Erling Smørgrav /*
334d95e11bfSDag-Erling Smørgrav * If we have setauthdb, retrieve the password registry for the user's
335efcad6b7SDag-Erling Smørgrav * account then feed it to setauthdb. This will mean that subsequent AIX auth
336efcad6b7SDag-Erling Smørgrav * functions will only use the specified loadable module. If we don't have
337efcad6b7SDag-Erling Smørgrav * setauthdb this is a no-op.
338d95e11bfSDag-Erling Smørgrav */
339d95e11bfSDag-Erling Smørgrav void
aix_setauthdb(const char * user)340d95e11bfSDag-Erling Smørgrav aix_setauthdb(const char *user)
341d95e11bfSDag-Erling Smørgrav {
342d95e11bfSDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB
343efcad6b7SDag-Erling Smørgrav char *registry;
344d95e11bfSDag-Erling Smørgrav
345d95e11bfSDag-Erling Smørgrav if (setuserdb(S_READ) == -1) {
346d95e11bfSDag-Erling Smørgrav debug3("%s: Could not open userdb to read", __func__);
347d95e11bfSDag-Erling Smørgrav return;
348d95e11bfSDag-Erling Smørgrav }
349d95e11bfSDag-Erling Smørgrav
350d95e11bfSDag-Erling Smørgrav if (getuserattr((char *)user, S_REGISTRY, ®istry, SEC_CHAR) == 0) {
351efcad6b7SDag-Erling Smørgrav if (setauthdb(registry, old_registry) == 0)
352efcad6b7SDag-Erling Smørgrav debug3("AIX/setauthdb set registry '%s'", registry);
353d95e11bfSDag-Erling Smørgrav else
354efcad6b7SDag-Erling Smørgrav debug3("AIX/setauthdb set registry '%s' failed: %s",
355efcad6b7SDag-Erling Smørgrav registry, strerror(errno));
356d95e11bfSDag-Erling Smørgrav } else
357d95e11bfSDag-Erling Smørgrav debug3("%s: Could not read S_REGISTRY for user: %s", __func__,
358d95e11bfSDag-Erling Smørgrav strerror(errno));
359d95e11bfSDag-Erling Smørgrav enduserdb();
360efcad6b7SDag-Erling Smørgrav # endif /* HAVE_SETAUTHDB */
361d95e11bfSDag-Erling Smørgrav }
36283d2307dSDag-Erling Smørgrav
363efcad6b7SDag-Erling Smørgrav /*
364efcad6b7SDag-Erling Smørgrav * Restore the user's registry settings from old_registry.
365efcad6b7SDag-Erling Smørgrav * Note that if the first aix_setauthdb fails, setauthdb("") is still safe
366efcad6b7SDag-Erling Smørgrav * (it restores the system default behaviour). If we don't have setauthdb,
367efcad6b7SDag-Erling Smørgrav * this is a no-op.
368efcad6b7SDag-Erling Smørgrav */
369efcad6b7SDag-Erling Smørgrav void
aix_restoreauthdb(void)370efcad6b7SDag-Erling Smørgrav aix_restoreauthdb(void)
371efcad6b7SDag-Erling Smørgrav {
372efcad6b7SDag-Erling Smørgrav # ifdef HAVE_SETAUTHDB
373efcad6b7SDag-Erling Smørgrav if (setauthdb(old_registry, NULL) == 0)
374efcad6b7SDag-Erling Smørgrav debug3("%s: restoring old registry '%s'", __func__,
375efcad6b7SDag-Erling Smørgrav old_registry);
376efcad6b7SDag-Erling Smørgrav else
377efcad6b7SDag-Erling Smørgrav debug3("%s: failed to restore old registry %s", __func__,
378efcad6b7SDag-Erling Smørgrav old_registry);
379efcad6b7SDag-Erling Smørgrav # endif /* HAVE_SETAUTHDB */
380efcad6b7SDag-Erling Smørgrav }
381efcad6b7SDag-Erling Smørgrav
382efcad6b7SDag-Erling Smørgrav # endif /* WITH_AIXAUTHENTICATE */
383efcad6b7SDag-Erling Smørgrav
384b15c8340SDag-Erling Smørgrav # ifdef USE_AIX_KRB_NAME
385b15c8340SDag-Erling Smørgrav /*
386*19261079SEd Maste * aix_krb5_get_principal_name: returns the user's kerberos client principal
387*19261079SEd Maste * name if configured, otherwise NULL. Caller must free returned string.
388b15c8340SDag-Erling Smørgrav */
389b15c8340SDag-Erling Smørgrav char *
aix_krb5_get_principal_name(const char * const_pw_name)390*19261079SEd Maste aix_krb5_get_principal_name(const char *const_pw_name)
391b15c8340SDag-Erling Smørgrav {
392*19261079SEd Maste char *pw_name = (char *)const_pw_name;
393b15c8340SDag-Erling Smørgrav char *authname = NULL, *authdomain = NULL, *principal = NULL;
394b15c8340SDag-Erling Smørgrav
395b15c8340SDag-Erling Smørgrav setuserdb(S_READ);
396b15c8340SDag-Erling Smørgrav if (getuserattr(pw_name, S_AUTHDOMAIN, &authdomain, SEC_CHAR) != 0)
397b15c8340SDag-Erling Smørgrav debug("AIX getuserattr S_AUTHDOMAIN: %s", strerror(errno));
398b15c8340SDag-Erling Smørgrav if (getuserattr(pw_name, S_AUTHNAME, &authname, SEC_CHAR) != 0)
399b15c8340SDag-Erling Smørgrav debug("AIX getuserattr S_AUTHNAME: %s", strerror(errno));
400b15c8340SDag-Erling Smørgrav
401b15c8340SDag-Erling Smørgrav if (authdomain != NULL)
402*19261079SEd Maste xasprintf(&principal, "%s@%s", authname ? authname : pw_name,
403*19261079SEd Maste authdomain);
404b15c8340SDag-Erling Smørgrav else if (authname != NULL)
405b15c8340SDag-Erling Smørgrav principal = xstrdup(authname);
406b15c8340SDag-Erling Smørgrav enduserdb();
407b15c8340SDag-Erling Smørgrav return principal;
408b15c8340SDag-Erling Smørgrav }
409b15c8340SDag-Erling Smørgrav # endif /* USE_AIX_KRB_NAME */
410b15c8340SDag-Erling Smørgrav
4115e8dbd04SDag-Erling Smørgrav # if defined(AIX_GETNAMEINFO_HACK) && !defined(BROKEN_ADDRINFO)
4125e8dbd04SDag-Erling Smørgrav # undef getnameinfo
4135e8dbd04SDag-Erling Smørgrav /*
4145e8dbd04SDag-Erling Smørgrav * For some reason, AIX's getnameinfo will refuse to resolve the all-zeros
4155e8dbd04SDag-Erling Smørgrav * IPv6 address into its textual representation ("::"), so we wrap it
4165e8dbd04SDag-Erling Smørgrav * with a function that will.
4175e8dbd04SDag-Erling Smørgrav */
4185e8dbd04SDag-Erling Smørgrav int
sshaix_getnameinfo(const struct sockaddr * sa,size_t salen,char * host,size_t hostlen,char * serv,size_t servlen,int flags)4195e8dbd04SDag-Erling Smørgrav sshaix_getnameinfo(const struct sockaddr *sa, size_t salen, char *host,
4205e8dbd04SDag-Erling Smørgrav size_t hostlen, char *serv, size_t servlen, int flags)
4215e8dbd04SDag-Erling Smørgrav {
4225e8dbd04SDag-Erling Smørgrav struct sockaddr_in6 *sa6;
4235e8dbd04SDag-Erling Smørgrav u_int32_t *a6;
4245e8dbd04SDag-Erling Smørgrav
4255e8dbd04SDag-Erling Smørgrav if (flags & (NI_NUMERICHOST|NI_NUMERICSERV) &&
4265e8dbd04SDag-Erling Smørgrav sa->sa_family == AF_INET6) {
4275e8dbd04SDag-Erling Smørgrav sa6 = (struct sockaddr_in6 *)sa;
4285e8dbd04SDag-Erling Smørgrav a6 = sa6->sin6_addr.u6_addr.u6_addr32;
4295e8dbd04SDag-Erling Smørgrav
4305e8dbd04SDag-Erling Smørgrav if (a6[0] == 0 && a6[1] == 0 && a6[2] == 0 && a6[3] == 0) {
4315e8dbd04SDag-Erling Smørgrav strlcpy(host, "::", hostlen);
4325e8dbd04SDag-Erling Smørgrav snprintf(serv, servlen, "%d", sa6->sin6_port);
4335e8dbd04SDag-Erling Smørgrav return 0;
4345e8dbd04SDag-Erling Smørgrav }
4355e8dbd04SDag-Erling Smørgrav }
4365e8dbd04SDag-Erling Smørgrav return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
4375e8dbd04SDag-Erling Smørgrav }
4385e8dbd04SDag-Erling Smørgrav # endif /* AIX_GETNAMEINFO_HACK */
4395e8dbd04SDag-Erling Smørgrav
440d4af9e69SDag-Erling Smørgrav # if defined(USE_GETGRSET)
441d4af9e69SDag-Erling Smørgrav # include <stdlib.h>
442d4af9e69SDag-Erling Smørgrav int
getgrouplist(const char * user,gid_t pgid,gid_t * groups,int * grpcnt)443d4af9e69SDag-Erling Smørgrav getgrouplist(const char *user, gid_t pgid, gid_t *groups, int *grpcnt)
444d4af9e69SDag-Erling Smørgrav {
445d4af9e69SDag-Erling Smørgrav char *cp, *grplist, *grp;
446d4af9e69SDag-Erling Smørgrav gid_t gid;
447d4af9e69SDag-Erling Smørgrav int ret = 0, ngroups = 0, maxgroups;
448*19261079SEd Maste long long ll;
449d4af9e69SDag-Erling Smørgrav
450d4af9e69SDag-Erling Smørgrav maxgroups = *grpcnt;
451d4af9e69SDag-Erling Smørgrav
452d4af9e69SDag-Erling Smørgrav if ((cp = grplist = getgrset(user)) == NULL)
453d4af9e69SDag-Erling Smørgrav return -1;
454d4af9e69SDag-Erling Smørgrav
455d4af9e69SDag-Erling Smørgrav /* handle zero-length case */
456d4af9e69SDag-Erling Smørgrav if (maxgroups <= 0) {
457d4af9e69SDag-Erling Smørgrav *grpcnt = 0;
458d4af9e69SDag-Erling Smørgrav return -1;
459d4af9e69SDag-Erling Smørgrav }
460d4af9e69SDag-Erling Smørgrav
461d4af9e69SDag-Erling Smørgrav /* copy primary group */
462d4af9e69SDag-Erling Smørgrav groups[ngroups++] = pgid;
463d4af9e69SDag-Erling Smørgrav
464d4af9e69SDag-Erling Smørgrav /* copy each entry from getgrset into group list */
465d4af9e69SDag-Erling Smørgrav while ((grp = strsep(&grplist, ",")) != NULL) {
466*19261079SEd Maste ll = strtoll(grp, NULL, 10);
467*19261079SEd Maste if (ngroups >= maxgroups || ll < 0 || ll > UID_MAX) {
468d4af9e69SDag-Erling Smørgrav ret = -1;
469d4af9e69SDag-Erling Smørgrav goto out;
470d4af9e69SDag-Erling Smørgrav }
471*19261079SEd Maste gid = (gid_t)ll;
472d4af9e69SDag-Erling Smørgrav if (gid == pgid)
473d4af9e69SDag-Erling Smørgrav continue; /* we have already added primary gid */
474d4af9e69SDag-Erling Smørgrav groups[ngroups++] = gid;
475d4af9e69SDag-Erling Smørgrav }
476d4af9e69SDag-Erling Smørgrav out:
477d4af9e69SDag-Erling Smørgrav free(cp);
478d4af9e69SDag-Erling Smørgrav *grpcnt = ngroups;
479d4af9e69SDag-Erling Smørgrav return ret;
480d4af9e69SDag-Erling Smørgrav }
481d4af9e69SDag-Erling Smørgrav # endif /* USE_GETGRSET */
482d4af9e69SDag-Erling Smørgrav
483efcad6b7SDag-Erling Smørgrav #endif /* _AIX */
484