diff options
Diffstat (limited to 'openbsd-compat/port-aix.c')
-rw-r--r-- | openbsd-compat/port-aix.c | 140 |
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 | ||
38 | extern ServerOptions options; | 40 | extern ServerOptions options; |
41 | extern Buffer loginmsg; | ||
42 | |||
43 | # ifdef HAVE_SETAUTHDB | ||
44 | static 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 | */ | ||
101 | int | ||
102 | sys_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 | */ |
92 | void | 171 | void |
93 | record_failed_login(const char *user, const char *ttyname) | 172 | record_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 | */ |
113 | void | 195 | void |
114 | aix_setauthdb(const char *user) | 196 | aix_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, ®istry, SEC_CHAR) == 0) { | 206 | if (getuserattr((char *)user, S_REGISTRY, ®istry, 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 | */ | ||
225 | void | ||
226 | aix_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 */ | ||