summaryrefslogtreecommitdiff
path: root/auth1.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth1.c')
-rw-r--r--auth1.c328
1 files changed, 195 insertions, 133 deletions
diff --git a/auth1.c b/auth1.c
index d08928455..4bc2bf76d 100644
--- a/auth1.c
+++ b/auth1.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $"); 13RCSID("$OpenBSD: auth1.c,v 1.62 2005/07/16 01:35:24 djm Exp $");
14 14
15#include "xmalloc.h" 15#include "xmalloc.h"
16#include "rsa.h" 16#include "rsa.h"
@@ -31,28 +31,182 @@ RCSID("$OpenBSD: auth1.c,v 1.59 2004/07/28 09:40:29 markus Exp $");
31extern ServerOptions options; 31extern ServerOptions options;
32extern Buffer loginmsg; 32extern Buffer loginmsg;
33 33
34/* 34static int auth1_process_password(Authctxt *, char *, size_t);
35 * convert ssh auth msg type into description 35static int auth1_process_rsa(Authctxt *, char *, size_t);
36 */ 36static int auth1_process_rhosts_rsa(Authctxt *, char *, size_t);
37static int auth1_process_tis_challenge(Authctxt *, char *, size_t);
38static int auth1_process_tis_response(Authctxt *, char *, size_t);
39
40static char *client_user = NULL; /* Used to fill in remote user for PAM */
41
42struct AuthMethod1 {
43 int type;
44 char *name;
45 int *enabled;
46 int (*method)(Authctxt *, char *, size_t);
47};
48
49const struct AuthMethod1 auth1_methods[] = {
50 {
51 SSH_CMSG_AUTH_PASSWORD, "password",
52 &options.password_authentication, auth1_process_password
53 },
54 {
55 SSH_CMSG_AUTH_RSA, "rsa",
56 &options.rsa_authentication, auth1_process_rsa
57 },
58 {
59 SSH_CMSG_AUTH_RHOSTS_RSA, "rhosts-rsa",
60 &options.rhosts_rsa_authentication, auth1_process_rhosts_rsa
61 },
62 {
63 SSH_CMSG_AUTH_TIS, "challenge-response",
64 &options.challenge_response_authentication,
65 auth1_process_tis_challenge
66 },
67 {
68 SSH_CMSG_AUTH_TIS_RESPONSE, "challenge-response",
69 &options.challenge_response_authentication,
70 auth1_process_tis_response
71 },
72 { -1, NULL, NULL, NULL}
73};
74
75static const struct AuthMethod1
76*lookup_authmethod1(int type)
77{
78 int i;
79
80 for(i = 0; auth1_methods[i].name != NULL; i++)
81 if (auth1_methods[i].type == type)
82 return (&(auth1_methods[i]));
83
84 return (NULL);
85}
86
37static char * 87static char *
38get_authname(int type) 88get_authname(int type)
39{ 89{
40 static char buf[1024]; 90 const struct AuthMethod1 *a;
41 switch (type) { 91 static char buf[64];
42 case SSH_CMSG_AUTH_PASSWORD: 92
43 return "password"; 93 if ((a = lookup_authmethod1(type)) != NULL)
44 case SSH_CMSG_AUTH_RSA: 94 return (a->name);
45 return "rsa"; 95 snprintf(buf, sizeof(buf), "bad-auth-msg-%d", type);
46 case SSH_CMSG_AUTH_RHOSTS_RSA: 96 return (buf);
47 return "rhosts-rsa"; 97}
48 case SSH_CMSG_AUTH_RHOSTS: 98
49 return "rhosts"; 99static int
50 case SSH_CMSG_AUTH_TIS: 100auth1_process_password(Authctxt *authctxt, char *info, size_t infolen)
51 case SSH_CMSG_AUTH_TIS_RESPONSE: 101{
52 return "challenge-response"; 102 int authenticated = 0;
103 char *password;
104 u_int dlen;
105
106 /*
107 * Read user password. It is in plain text, but was
108 * transmitted over the encrypted channel so it is
109 * not visible to an outside observer.
110 */
111 password = packet_get_string(&dlen);
112 packet_check_eom();
113
114 /* Try authentication with the password. */
115 authenticated = PRIVSEP(auth_password(authctxt, password));
116
117 memset(password, 0, dlen);
118 xfree(password);
119
120 return (authenticated);
121}
122
123static int
124auth1_process_rsa(Authctxt *authctxt, char *info, size_t infolen)
125{
126 int authenticated = 0;
127 BIGNUM *n;
128
129 /* RSA authentication requested. */
130 if ((n = BN_new()) == NULL)
131 fatal("do_authloop: BN_new failed");
132 packet_get_bignum(n);
133 packet_check_eom();
134 authenticated = auth_rsa(authctxt, n);
135 BN_clear_free(n);
136
137 return (authenticated);
138}
139
140static int
141auth1_process_rhosts_rsa(Authctxt *authctxt, char *info, size_t infolen)
142{
143 int keybits, authenticated = 0;
144 u_int bits;
145 Key *client_host_key;
146 u_int ulen;
147
148 /*
149 * Get client user name. Note that we just have to
150 * trust the client; root on the client machine can
151 * claim to be any user.
152 */
153 client_user = packet_get_string(&ulen);
154
155 /* Get the client host key. */
156 client_host_key = key_new(KEY_RSA1);
157 bits = packet_get_int();
158 packet_get_bignum(client_host_key->rsa->e);
159 packet_get_bignum(client_host_key->rsa->n);
160
161 keybits = BN_num_bits(client_host_key->rsa->n);
162 if (keybits < 0 || bits != (u_int)keybits) {
163 verbose("Warning: keysize mismatch for client_host_key: "
164 "actual %d, announced %d",
165 BN_num_bits(client_host_key->rsa->n), bits);
53 } 166 }
54 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); 167 packet_check_eom();
55 return buf; 168
169 authenticated = auth_rhosts_rsa(authctxt, client_user,
170 client_host_key);
171 key_free(client_host_key);
172
173 snprintf(info, infolen, " ruser %.100s", client_user);
174
175 return (authenticated);
176}
177
178static int
179auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
180{
181 char *challenge;
182
183 if ((challenge = get_challenge(authctxt)) == NULL)
184 return (0);
185
186 debug("sending challenge '%s'", challenge);
187 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
188 packet_put_cstring(challenge);
189 xfree(challenge);
190 packet_send();
191 packet_write_wait();
192
193 return (-1);
194}
195
196static int
197auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
198{
199 int authenticated = 0;
200 char *response;
201 u_int dlen;
202
203 response = packet_get_string(&dlen);
204 packet_check_eom();
205 authenticated = verify_response(authctxt, response);
206 memset(response, 'r', dlen);
207 xfree(response);
208
209 return (authenticated);
56} 210}
57 211
58/* 212/*
@@ -63,14 +217,9 @@ static void
63do_authloop(Authctxt *authctxt) 217do_authloop(Authctxt *authctxt)
64{ 218{
65 int authenticated = 0; 219 int authenticated = 0;
66 u_int bits;
67 Key *client_host_key;
68 BIGNUM *n;
69 char *client_user, *password;
70 char info[1024]; 220 char info[1024];
71 u_int dlen; 221 int prev = 0, type = 0;
72 u_int ulen; 222 const struct AuthMethod1 *meth;
73 int prev, type = 0;
74 223
75 debug("Attempting authentication for %s%.100s.", 224 debug("Attempting authentication for %s%.100s.",
76 authctxt->valid ? "" : "invalid user ", authctxt->user); 225 authctxt->valid ? "" : "invalid user ", authctxt->user);
@@ -95,8 +244,6 @@ do_authloop(Authctxt *authctxt)
95 packet_send(); 244 packet_send();
96 packet_write_wait(); 245 packet_write_wait();
97 246
98 client_user = NULL;
99
100 for (;;) { 247 for (;;) {
101 /* default to fail */ 248 /* default to fail */
102 authenticated = 0; 249 authenticated = 0;
@@ -118,107 +265,21 @@ do_authloop(Authctxt *authctxt)
118 type != SSH_CMSG_AUTH_TIS_RESPONSE) 265 type != SSH_CMSG_AUTH_TIS_RESPONSE)
119 abandon_challenge_response(authctxt); 266 abandon_challenge_response(authctxt);
120 267
121 /* Process the packet. */ 268 if ((meth = lookup_authmethod1(type)) == NULL) {
122 switch (type) { 269 logit("Unknown message during authentication: "
123 case SSH_CMSG_AUTH_RHOSTS_RSA: 270 "type %d", type);
124 if (!options.rhosts_rsa_authentication) { 271 goto skip;
125 verbose("Rhosts with RSA authentication disabled."); 272 }
126 break; 273
127 } 274 if (!*(meth->enabled)) {
128 /* 275 verbose("%s authentication disabled.", meth->name);
129 * Get client user name. Note that we just have to 276 goto skip;
130 * trust the client; root on the client machine can
131 * claim to be any user.
132 */
133 client_user = packet_get_string(&ulen);
134
135 /* Get the client host key. */
136 client_host_key = key_new(KEY_RSA1);
137 bits = packet_get_int();
138 packet_get_bignum(client_host_key->rsa->e);
139 packet_get_bignum(client_host_key->rsa->n);
140
141 if (bits != BN_num_bits(client_host_key->rsa->n))
142 verbose("Warning: keysize mismatch for client_host_key: "
143 "actual %d, announced %d",
144 BN_num_bits(client_host_key->rsa->n), bits);
145 packet_check_eom();
146
147 authenticated = auth_rhosts_rsa(authctxt, client_user,
148 client_host_key);
149 key_free(client_host_key);
150
151 snprintf(info, sizeof info, " ruser %.100s", client_user);
152 break;
153
154 case SSH_CMSG_AUTH_RSA:
155 if (!options.rsa_authentication) {
156 verbose("RSA authentication disabled.");
157 break;
158 }
159 /* RSA authentication requested. */
160 if ((n = BN_new()) == NULL)
161 fatal("do_authloop: BN_new failed");
162 packet_get_bignum(n);
163 packet_check_eom();
164 authenticated = auth_rsa(authctxt, n);
165 BN_clear_free(n);
166 break;
167
168 case SSH_CMSG_AUTH_PASSWORD:
169 if (!options.password_authentication) {
170 verbose("Password authentication disabled.");
171 break;
172 }
173 /*
174 * Read user password. It is in plain text, but was
175 * transmitted over the encrypted channel so it is
176 * not visible to an outside observer.
177 */
178 password = packet_get_string(&dlen);
179 packet_check_eom();
180
181 /* Try authentication with the password. */
182 authenticated = PRIVSEP(auth_password(authctxt, password));
183
184 memset(password, 0, strlen(password));
185 xfree(password);
186 break;
187
188 case SSH_CMSG_AUTH_TIS:
189 debug("rcvd SSH_CMSG_AUTH_TIS");
190 if (options.challenge_response_authentication == 1) {
191 char *challenge = get_challenge(authctxt);
192 if (challenge != NULL) {
193 debug("sending challenge '%s'", challenge);
194 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
195 packet_put_cstring(challenge);
196 xfree(challenge);
197 packet_send();
198 packet_write_wait();
199 continue;
200 }
201 }
202 break;
203 case SSH_CMSG_AUTH_TIS_RESPONSE:
204 debug("rcvd SSH_CMSG_AUTH_TIS_RESPONSE");
205 if (options.challenge_response_authentication == 1) {
206 char *response = packet_get_string(&dlen);
207 packet_check_eom();
208 authenticated = verify_response(authctxt, response);
209 memset(response, 'r', dlen);
210 xfree(response);
211 }
212 break;
213
214 default:
215 /*
216 * Any unknown messages will be ignored (and failure
217 * returned) during authentication.
218 */
219 logit("Unknown message during authentication: type %d", type);
220 break;
221 } 277 }
278
279 authenticated = meth->method(authctxt, info, sizeof(info));
280 if (authenticated == -1)
281 continue; /* "postponed" */
282
222#ifdef BSD_AUTH 283#ifdef BSD_AUTH
223 if (authctxt->as) { 284 if (authctxt->as) {
224 auth_close(authctxt->as); 285 auth_close(authctxt->as);
@@ -238,7 +299,7 @@ do_authloop(Authctxt *authctxt)
238 299
239#ifdef HAVE_CYGWIN 300#ifdef HAVE_CYGWIN
240 if (authenticated && 301 if (authenticated &&
241 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD, 302 !check_nt_auth(type == SSH_CMSG_AUTH_PASSWORD,
242 authctxt->pw)) { 303 authctxt->pw)) {
243 packet_disconnect("Authentication rejected for uid %d.", 304 packet_disconnect("Authentication rejected for uid %d.",
244 authctxt->pw == NULL ? -1 : authctxt->pw->pw_uid); 305 authctxt->pw == NULL ? -1 : authctxt->pw->pw_uid);
@@ -247,8 +308,8 @@ do_authloop(Authctxt *authctxt)
247#else 308#else
248 /* Special handling for root */ 309 /* Special handling for root */
249 if (authenticated && authctxt->pw->pw_uid == 0 && 310 if (authenticated && authctxt->pw->pw_uid == 0 &&
250 !auth_root_allowed(get_authname(type))) { 311 !auth_root_allowed(meth->name)) {
251 authenticated = 0; 312 authenticated = 0;
252# ifdef SSH_AUDIT_EVENTS 313# ifdef SSH_AUDIT_EVENTS
253 PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); 314 PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
254# endif 315# endif
@@ -262,7 +323,7 @@ do_authloop(Authctxt *authctxt)
262 size_t len; 323 size_t len;
263 324
264 error("Access denied for user %s by PAM account " 325 error("Access denied for user %s by PAM account "
265 "configuration", authctxt->user); 326 "configuration", authctxt->user);
266 len = buffer_len(&loginmsg); 327 len = buffer_len(&loginmsg);
267 buffer_append(&loginmsg, "\0", 1); 328 buffer_append(&loginmsg, "\0", 1);
268 msg = buffer_ptr(&loginmsg); 329 msg = buffer_ptr(&loginmsg);
@@ -276,6 +337,7 @@ do_authloop(Authctxt *authctxt)
276 } 337 }
277#endif 338#endif
278 339
340 skip:
279 /* Log before sending the reply */ 341 /* Log before sending the reply */
280 auth_log(authctxt, authenticated, get_authname(type), info); 342 auth_log(authctxt, authenticated, get_authname(type), info);
281 343
@@ -341,7 +403,7 @@ do_authentication(Authctxt *authctxt)
341 403
342 /* 404 /*
343 * If we are not running as root, the user must have the same uid as 405 * If we are not running as root, the user must have the same uid as
344 * the server. (Unless you are running Windows) 406 * the server.
345 */ 407 */
346#ifndef HAVE_CYGWIN 408#ifndef HAVE_CYGWIN
347 if (!use_privsep && getuid() != 0 && authctxt->pw && 409 if (!use_privsep && getuid() != 0 && authctxt->pw &&