00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "includes.h"
00026 RCSID("$OpenBSD: auth2.c,v 1.107 2004/07/28 09:40:29 markus Exp $");
00027
00028 #include "ssh2.h"
00029 #include "xmalloc.h"
00030 #include "packet.h"
00031 #include "log.h"
00032 #include "servconf.h"
00033 #include "compat.h"
00034 #include "auth.h"
00035 #include "dispatch.h"
00036 #include "pathnames.h"
00037 #include "monitor_wrap.h"
00038 #include "buffer.h"
00039
00040 #ifdef GSSAPI
00041 #include "ssh-gss.h"
00042 #endif
00043
00044
00045 extern ServerOptions options;
00046 extern u_char *session_id2;
00047 extern u_int session_id2_len;
00048 extern Buffer loginmsg;
00049
00050
00051
00052 extern Authmethod method_none;
00053 extern Authmethod method_pubkey;
00054 extern Authmethod method_passwd;
00055 extern Authmethod method_kbdint;
00056 extern Authmethod method_hostbased;
00057 #ifdef GSSAPI
00058 extern Authmethod method_gssapi;
00059 #endif
00060
00061 Authmethod *authmethods[] = {
00062 &method_none,
00063 &method_pubkey,
00064 #ifdef GSSAPI
00065 &method_gssapi,
00066 #endif
00067 &method_passwd,
00068 &method_kbdint,
00069 &method_hostbased,
00070 NULL
00071 };
00072
00073
00074
00075 static void input_service_request(int, u_int32_t, void *);
00076 static void input_userauth_request(int, u_int32_t, void *);
00077
00078
00079 static Authmethod *authmethod_lookup(const char *);
00080 static char *authmethods_get(void);
00081 int user_key_allowed(struct passwd *, Key *);
00082
00083
00084
00085
00086
00087 void
00088 do_authentication2(Authctxt *authctxt)
00089 {
00090
00091 if (options.challenge_response_authentication)
00092 options.kbd_interactive_authentication = 1;
00093
00094 dispatch_init(&dispatch_protocol_error);
00095 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
00096 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
00097 }
00098
00099 static void
00100 input_service_request(int type, u_int32_t seq, void *ctxt)
00101 {
00102 Authctxt *authctxt = ctxt;
00103 u_int len;
00104 int acceptit = 0;
00105 char *service = packet_get_string(&len);
00106 packet_check_eom();
00107
00108 if (authctxt == NULL)
00109 fatal("input_service_request: no authctxt");
00110
00111 if (strcmp(service, "ssh-userauth") == 0) {
00112 if (!authctxt->success) {
00113 acceptit = 1;
00114
00115 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
00116 }
00117 }
00118
00119
00120 if (acceptit) {
00121 packet_start(SSH2_MSG_SERVICE_ACCEPT);
00122 packet_put_cstring(service);
00123 packet_send();
00124 packet_write_wait();
00125 } else {
00126 debug("bad service request %s", service);
00127 packet_disconnect("bad service request %s", service);
00128 }
00129 xfree(service);
00130 }
00131
00132 static void
00133 input_userauth_request(int type, u_int32_t seq, void *ctxt)
00134 {
00135 Authctxt *authctxt = ctxt;
00136 Authmethod *m = NULL;
00137 char *user, *service, *method, *style = NULL;
00138 int authenticated = 0;
00139
00140 if (authctxt == NULL)
00141 fatal("input_userauth_request: no authctxt");
00142
00143 user = packet_get_string(NULL);
00144 service = packet_get_string(NULL);
00145 method = packet_get_string(NULL);
00146 debug("userauth-request for user %s service %s method %s", user, service, method);
00147 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
00148
00149 if ((style = strchr(user, ':')) != NULL)
00150 *style++ = 0;
00151
00152 if (authctxt->attempt++ == 0) {
00153
00154 authctxt->pw = PRIVSEP(getpwnamallow(user));
00155 authctxt->user = xstrdup(user);
00156 if (authctxt->pw && strcmp(service, "ssh-connection")==0) {
00157 authctxt->valid = 1;
00158 debug2("input_userauth_request: setting up authctxt for %s", user);
00159 } else {
00160 logit("input_userauth_request: invalid user %s", user);
00161 authctxt->pw = fakepw();
00162 #ifdef SSH_AUDIT_EVENTS
00163 PRIVSEP(audit_event(SSH_INVALID_USER));
00164 #endif
00165 }
00166 #ifdef USE_PAM
00167 if (options.use_pam)
00168 PRIVSEP(start_pam(authctxt));
00169 #endif
00170 setproctitle("%s%s", authctxt->valid ? user : "unknown",
00171 use_privsep ? " [net]" : "");
00172 authctxt->service = xstrdup(service);
00173 authctxt->style = style ? xstrdup(style) : NULL;
00174 if (use_privsep)
00175 mm_inform_authserv(service, style);
00176 } else if (strcmp(user, authctxt->user) != 0 ||
00177 strcmp(service, authctxt->service) != 0) {
00178 packet_disconnect("Change of username or service not allowed: "
00179 "(%s,%s) -> (%s,%s)",
00180 authctxt->user, authctxt->service, user, service);
00181 }
00182
00183 auth2_challenge_stop(authctxt);
00184
00185 #ifdef GSSAPI
00186 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
00187 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE, NULL);
00188 #endif
00189
00190 authctxt->postponed = 0;
00191
00192
00193 m = authmethod_lookup(method);
00194 if (m != NULL) {
00195 debug2("input_userauth_request: try method %s", method);
00196 authenticated = m->userauth(authctxt);
00197 }
00198 userauth_finish(authctxt, authenticated, method);
00199
00200 xfree(service);
00201 xfree(user);
00202 xfree(method);
00203 }
00204
00205 void
00206 userauth_finish(Authctxt *authctxt, int authenticated, char *method)
00207 {
00208 char *methods;
00209
00210 if (!authctxt->valid && authenticated)
00211 fatal("INTERNAL ERROR: authenticated invalid user %s",
00212 authctxt->user);
00213
00214
00215 if (authenticated && authctxt->pw->pw_uid == 0 &&
00216 !auth_root_allowed(method)) {
00217 authenticated = 0;
00218 #ifdef SSH_AUDIT_EVENTS
00219 PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
00220 #endif
00221 }
00222
00223 #ifdef USE_PAM
00224 if (options.use_pam && authenticated) {
00225 if (!PRIVSEP(do_pam_account())) {
00226
00227 if (buffer_len(&loginmsg) > 0) {
00228 buffer_append(&loginmsg, "\0", 1);
00229 userauth_send_banner(buffer_ptr(&loginmsg));
00230 packet_write_wait();
00231 }
00232 fatal("Access denied for user %s by PAM account "
00233 "configuration", authctxt->user);
00234 }
00235 }
00236 #endif
00237
00238 #ifdef _UNICOS
00239 if (authenticated && cray_access_denied(authctxt->user)) {
00240 authenticated = 0;
00241 fatal("Access denied for user %s.",authctxt->user);
00242 }
00243 #endif
00244
00245
00246 auth_log(authctxt, authenticated, method, " ssh2");
00247
00248 if (authctxt->postponed)
00249 return;
00250
00251
00252 if (authenticated == 1) {
00253
00254 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &dispatch_protocol_ignore);
00255 packet_start(SSH2_MSG_USERAUTH_SUCCESS);
00256 packet_send();
00257 packet_write_wait();
00258
00259 authctxt->success = 1;
00260 } else {
00261 if (authctxt->failures++ > options.max_authtries) {
00262 #ifdef SSH_AUDIT_EVENTS
00263 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
00264 #endif
00265 packet_disconnect(AUTH_FAIL_MSG, authctxt->user);
00266 }
00267 methods = authmethods_get();
00268 packet_start(SSH2_MSG_USERAUTH_FAILURE);
00269 packet_put_cstring(methods);
00270 packet_put_char(0);
00271 packet_send();
00272 packet_write_wait();
00273 xfree(methods);
00274 }
00275 }
00276
00277 #define DELIM ","
00278
00279 static char *
00280 authmethods_get(void)
00281 {
00282 Buffer b;
00283 char *list;
00284 int i;
00285
00286 buffer_init(&b);
00287 for (i = 0; authmethods[i] != NULL; i++) {
00288 if (strcmp(authmethods[i]->name, "none") == 0)
00289 continue;
00290 if (authmethods[i]->enabled != NULL &&
00291 *(authmethods[i]->enabled) != 0) {
00292 if (buffer_len(&b) > 0)
00293 buffer_append(&b, ",", 1);
00294 buffer_append(&b, authmethods[i]->name,
00295 strlen(authmethods[i]->name));
00296 }
00297 }
00298 buffer_append(&b, "\0", 1);
00299 list = xstrdup(buffer_ptr(&b));
00300 buffer_free(&b);
00301 return list;
00302 }
00303
00304 static Authmethod *
00305 authmethod_lookup(const char *name)
00306 {
00307 int i;
00308
00309 if (name != NULL)
00310 for (i = 0; authmethods[i] != NULL; i++)
00311 if (authmethods[i]->enabled != NULL &&
00312 *(authmethods[i]->enabled) != 0 &&
00313 strcmp(name, authmethods[i]->name) == 0)
00314 return authmethods[i];
00315 debug2("Unrecognized authentication method name: %s",
00316 name ? name : "NULL");
00317 return NULL;
00318 }