summaryrefslogtreecommitdiff
path: root/openbsd-compat/port-aix.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsd-compat/port-aix.c')
-rw-r--r--openbsd-compat/port-aix.c140
1 files changed, 119 insertions, 21 deletions
diff --git a/openbsd-compat/port-aix.c b/openbsd-compat/port-aix.c
index 9fbcce936..2895f0d44 100644
--- a/openbsd-compat/port-aix.c
+++ b/openbsd-compat/port-aix.c
@@ -24,11 +24,13 @@
24 * 24 *
25 */ 25 */
26#include "includes.h" 26#include "includes.h"
27#include "auth.h"
27#include "ssh.h" 28#include "ssh.h"
28#include "log.h" 29#include "log.h"
29#include "servconf.h" 30#include "servconf.h"
30#include "canohost.h" 31#include "canohost.h"
31#include "xmalloc.h" 32#include "xmalloc.h"
33#include "buffer.h"
32 34
33#ifdef _AIX 35#ifdef _AIX
34 36
@@ -36,6 +38,11 @@
36#include "port-aix.h" 38#include "port-aix.h"
37 39
38extern ServerOptions options; 40extern ServerOptions options;
41extern Buffer loginmsg;
42
43# ifdef HAVE_SETAUTHDB
44static char old_registry[REGISTRY_SIZE] = "";
45# endif
39 46
40/* 47/*
41 * AIX has a "usrinfo" area where logname and other stuff is stored - 48 * AIX has a "usrinfo" area where logname and other stuff is stored -
@@ -63,7 +70,7 @@ aix_usrinfo(struct passwd *pw)
63 xfree(cp); 70 xfree(cp);
64} 71}
65 72
66#ifdef WITH_AIXAUTHENTICATE 73# ifdef WITH_AIXAUTHENTICATE
67/* 74/*
68 * Remove embedded newlines in string (if any). 75 * Remove embedded newlines in string (if any).
69 * Used before logging messages returned by AIX authentication functions 76 * Used before logging messages returned by AIX authentication functions
@@ -83,41 +90,113 @@ aix_remove_embedded_newlines(char *p)
83 if (*--p == ' ') 90 if (*--p == ' ')
84 *p = '\0'; 91 *p = '\0';
85} 92}
86#endif /* WITH_AIXAUTHENTICATE */ 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 */
101int
102sys_auth_passwd(Authctxt *ctxt, const char *password)
103{
104 char *authmsg = NULL, *host, *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 host = (char *)get_canonical_hostname(options.use_dns);
119
120 /*
121 * Record successful login. We don't have a pty yet, so just
122 * label the line as "ssh"
123 */
124 aix_setauthdb(name);
125 if (loginsuccess((char *)name, (char *)host, "ssh", &msg) == 0) {
126 if (msg != NULL) {
127 debug("%s: msg %s", __func__, msg);
128 buffer_append(&loginmsg, msg, strlen(msg));
129 xfree(msg);
130 }
131 }
132
133 /*
134 * Check if the user's password is expired.
135 */
136 expired = passwdexpired(name, &msg);
137 if (msg && *msg) {
138 buffer_append(&loginmsg, msg, strlen(msg));
139 aix_remove_embedded_newlines(msg);
140 }
141 debug3("AIX/passwdexpired returned %d msg %.100s", expired, msg);
142
143 switch (expired) {
144 case 0: /* password not expired */
145 break;
146 case 1: /* expired, password change required */
147 ctxt->force_pwchange = 1;
148 disable_forwarding();
149 break;
150 default: /* user can't change(2) or other error (-1) */
151 logit("Password can't be changed for user %s: %.100s",
152 name, msg);
153 if (msg)
154 xfree(msg);
155 authsuccess = 0;
156 }
157
158 aix_restoreauthdb();
159 }
160
161 if (authmsg != NULL)
162 xfree(authmsg);
163
164 return authsuccess;
165}
87 166
88# ifdef CUSTOM_FAILED_LOGIN 167# ifdef CUSTOM_FAILED_LOGIN
89/* 168/*
90 * record_failed_login: generic "login failed" interface function 169 * record_failed_login: generic "login failed" interface function
91 */ 170 */
92void 171void
93record_failed_login(const char *user, const char *ttyname) 172record_failed_login(const char *user, const char *ttyname)
94{ 173{
95 char *hostname = get_canonical_hostname(options.use_dns); 174 char *hostname = (char *)get_canonical_hostname(options.use_dns);
96 175
97 if (geteuid() != 0) 176 if (geteuid() != 0)
98 return; 177 return;
99 178
100 aix_setauthdb(user); 179 aix_setauthdb(user);
101# ifdef AIX_LOGINFAILED_4ARG 180# ifdef AIX_LOGINFAILED_4ARG
102 loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH); 181 loginfailed((char *)user, hostname, (char *)ttyname, AUDIT_FAIL_AUTH);
103# else 182# else
104 loginfailed((char *)user, hostname, (char *)ttyname); 183 loginfailed((char *)user, hostname, (char *)ttyname);
105# endif 184# endif
185 aix_restoreauthdb();
106} 186}
187# endif /* CUSTOM_FAILED_LOGIN */
107 188
108/* 189/*
109 * If we have setauthdb, retrieve the password registry for the user's 190 * If we have setauthdb, retrieve the password registry for the user's
110 * account then feed it to setauthdb. This may load registry-specific method 191 * account then feed it to setauthdb. This will mean that subsequent AIX auth
111 * code. If we don't have setauthdb or have already called it this is a no-op. 192 * functions will only use the specified loadable module. If we don't have
193 * setauthdb this is a no-op.
112 */ 194 */
113void 195void
114aix_setauthdb(const char *user) 196aix_setauthdb(const char *user)
115{ 197{
116# ifdef HAVE_SETAUTHDB 198# ifdef HAVE_SETAUTHDB
117 static char *registry = NULL; 199 char *registry;
118
119 if (registry != NULL) /* have already done setauthdb */
120 return;
121 200
122 if (setuserdb(S_READ) == -1) { 201 if (setuserdb(S_READ) == -1) {
123 debug3("%s: Could not open userdb to read", __func__); 202 debug3("%s: Could not open userdb to read", __func__);
@@ -125,18 +204,37 @@ aix_setauthdb(const char *user)
125 } 204 }
126 205
127 if (getuserattr((char *)user, S_REGISTRY, &registry, SEC_CHAR) == 0) { 206 if (getuserattr((char *)user, S_REGISTRY, &registry, SEC_CHAR) == 0) {
128 if (setauthdb(registry, NULL) == 0) 207 if (setauthdb(registry, old_registry) == 0)
129 debug3("%s: AIX/setauthdb set registry %s", __func__, 208 debug3("AIX/setauthdb set registry '%s'", registry);
130 registry);
131 else 209 else
132 debug3("%s: AIX/setauthdb set registry %s failed: %s", 210 debug3("AIX/setauthdb set registry '%s' failed: %s",
133 __func__, registry, strerror(errno)); 211 registry, strerror(errno));
134 } else 212 } else
135 debug3("%s: Could not read S_REGISTRY for user: %s", __func__, 213 debug3("%s: Could not read S_REGISTRY for user: %s", __func__,
136 strerror(errno)); 214 strerror(errno));
137 enduserdb(); 215 enduserdb();
138# endif 216# endif /* HAVE_SETAUTHDB */
139} 217}
140# endif /* CUSTOM_FAILED_LOGIN */
141#endif /* _AIX */
142 218
219/*
220 * Restore the user's registry settings from old_registry.
221 * Note that if the first aix_setauthdb fails, setauthdb("") is still safe
222 * (it restores the system default behaviour). If we don't have setauthdb,
223 * this is a no-op.
224 */
225void
226aix_restoreauthdb(void)
227{
228# ifdef HAVE_SETAUTHDB
229 if (setauthdb(old_registry, NULL) == 0)
230 debug3("%s: restoring old registry '%s'", __func__,
231 old_registry);
232 else
233 debug3("%s: failed to restore old registry %s", __func__,
234 old_registry);
235# endif /* HAVE_SETAUTHDB */
236}
237
238# endif /* WITH_AIXAUTHENTICATE */
239
240#endif /* _AIX */