summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2005-06-19 07:31:37 +1000
committerDamien Miller <djm@mindrot.org>2005-06-19 07:31:37 +1000
commit6abf57ccbf13a043a2a2b7c8a662fc3e50d71d20 (patch)
tree603d697f6d2549cf4818e5338b7da9fd4926eac0
parentf0bd352429f26f99b7bdacd23baf46b39a9f600a (diff)
- djm@cvs.openbsd.org 2005/05/20 12:57:01;
[auth1.c] split protocol 1 auth methods into separate functions, makes authloop much more readable; fixes and ok markus@ (portable ok & polish dtucker@)
-rw-r--r--ChangeLog9
-rw-r--r--auth1.c323
2 files changed, 200 insertions, 132 deletions
diff --git a/ChangeLog b/ChangeLog
index 3cfba58a9..76e88a032 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
120050618
2 - (djm) OpenBSD CVS Sync
3 - djm@cvs.openbsd.org 2005/05/20 12:57:01;
4 [auth1.c] split protocol 1 auth methods into separate functions, makes
5 authloop much more readable; fixes and ok markus@ (portable ok &
6 polish dtucker@)
7
120050617 820050617
2 - (djm) OpenBSD CVS Sync 9 - (djm) OpenBSD CVS Sync
3 - djm@cvs.openbsd.org 2005/06/16 03:38:36 10 - djm@cvs.openbsd.org 2005/06/16 03:38:36
@@ -2738,4 +2745,4 @@
2738 - (djm) Trim deprecated options from INSTALL. Mention UsePAM 2745 - (djm) Trim deprecated options from INSTALL. Mention UsePAM
2739 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu 2746 - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
2740 2747
2741$Id: ChangeLog,v 1.3824 2005/06/17 11:15:20 dtucker Exp $ 2748$Id: ChangeLog,v 1.3825 2005/06/18 21:31:37 djm Exp $
diff --git a/auth1.c b/auth1.c
index d08928455..b7dfa987e 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.60 2005/05/20 12:57:01 djm Exp $");
14 14
15#include "xmalloc.h" 15#include "xmalloc.h"
16#include "rsa.h" 16#include "rsa.h"
@@ -31,28 +31,181 @@ 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 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 if (bits != BN_num_bits(client_host_key->rsa->n)) {
162 verbose("Warning: keysize mismatch for client_host_key: "
163 "actual %d, announced %d",
164 BN_num_bits(client_host_key->rsa->n), bits);
53 } 165 }
54 snprintf(buf, sizeof buf, "bad-auth-msg-%d", type); 166 packet_check_eom();
55 return buf; 167
168 authenticated = auth_rhosts_rsa(authctxt, client_user,
169 client_host_key);
170 key_free(client_host_key);
171
172 snprintf(info, infolen, " ruser %.100s", client_user);
173
174 return (authenticated);
175}
176
177static int
178auth1_process_tis_challenge(Authctxt *authctxt, char *info, size_t infolen)
179{
180 char *challenge;
181
182 if ((challenge = get_challenge(authctxt)) == NULL)
183 return (0);
184
185 debug("sending challenge '%s'", challenge);
186 packet_start(SSH_SMSG_AUTH_TIS_CHALLENGE);
187 packet_put_cstring(challenge);
188 xfree(challenge);
189 packet_send();
190 packet_write_wait();
191
192 return (-1);
193}
194
195static int
196auth1_process_tis_response(Authctxt *authctxt, char *info, size_t infolen)
197{
198 int authenticated = 0;
199 char *response;
200 u_int dlen;
201
202 response = packet_get_string(&dlen);
203 packet_check_eom();
204 authenticated = verify_response(authctxt, response);
205 memset(response, 'r', dlen);
206 xfree(response);
207
208 return (authenticated);
56} 209}
57 210
58/* 211/*
@@ -63,14 +216,9 @@ static void
63do_authloop(Authctxt *authctxt) 216do_authloop(Authctxt *authctxt)
64{ 217{
65 int authenticated = 0; 218 int authenticated = 0;
66 u_int bits;
67 Key *client_host_key;
68 BIGNUM *n;
69 char *client_user, *password;
70 char info[1024]; 219 char info[1024];
71 u_int dlen; 220 int prev = 0, type = 0;
72 u_int ulen; 221 const struct AuthMethod1 *meth;
73 int prev, type = 0;
74 222
75 debug("Attempting authentication for %s%.100s.", 223 debug("Attempting authentication for %s%.100s.",
76 authctxt->valid ? "" : "invalid user ", authctxt->user); 224 authctxt->valid ? "" : "invalid user ", authctxt->user);
@@ -95,8 +243,6 @@ do_authloop(Authctxt *authctxt)
95 packet_send(); 243 packet_send();
96 packet_write_wait(); 244 packet_write_wait();
97 245
98 client_user = NULL;
99
100 for (;;) { 246 for (;;) {
101 /* default to fail */ 247 /* default to fail */
102 authenticated = 0; 248 authenticated = 0;
@@ -118,107 +264,21 @@ do_authloop(Authctxt *authctxt)
118 type != SSH_CMSG_AUTH_TIS_RESPONSE) 264 type != SSH_CMSG_AUTH_TIS_RESPONSE)
119 abandon_challenge_response(authctxt); 265 abandon_challenge_response(authctxt);
120 266
121 /* Process the packet. */ 267 if ((meth = lookup_authmethod1(type)) == NULL) {
122 switch (type) { 268 logit("Unknown message during authentication: "
123 case SSH_CMSG_AUTH_RHOSTS_RSA: 269 "type %d", type);
124 if (!options.rhosts_rsa_authentication) { 270 goto skip;
125 verbose("Rhosts with RSA authentication disabled."); 271 }
126 break; 272
127 } 273 if (!*(meth->enabled)) {
128 /* 274 verbose("%s authentication disabled.", meth->name);
129 * Get client user name. Note that we just have to 275 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 } 276 }
277
278 authenticated = meth->method(authctxt, info, sizeof(info));
279 if (authenticated == -1)
280 continue; /* "postponed" */
281
222#ifdef BSD_AUTH 282#ifdef BSD_AUTH
223 if (authctxt->as) { 283 if (authctxt->as) {
224 auth_close(authctxt->as); 284 auth_close(authctxt->as);
@@ -247,8 +307,8 @@ do_authloop(Authctxt *authctxt)
247#else 307#else
248 /* Special handling for root */ 308 /* Special handling for root */
249 if (authenticated && authctxt->pw->pw_uid == 0 && 309 if (authenticated && authctxt->pw->pw_uid == 0 &&
250 !auth_root_allowed(get_authname(type))) { 310 !auth_root_allowed(meth->name)) {
251 authenticated = 0; 311 authenticated = 0;
252# ifdef SSH_AUDIT_EVENTS 312# ifdef SSH_AUDIT_EVENTS
253 PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED)); 313 PRIVSEP(audit_event(SSH_LOGIN_ROOT_DENIED));
254# endif 314# endif
@@ -276,6 +336,7 @@ do_authloop(Authctxt *authctxt)
276 } 336 }
277#endif 337#endif
278 338
339 skip:
279 /* Log before sending the reply */ 340 /* Log before sending the reply */
280 auth_log(authctxt, authenticated, get_authname(type), info); 341 auth_log(authctxt, authenticated, get_authname(type), info);
281 342
@@ -341,7 +402,7 @@ do_authentication(Authctxt *authctxt)
341 402
342 /* 403 /*
343 * If we are not running as root, the user must have the same uid as 404 * If we are not running as root, the user must have the same uid as
344 * the server. (Unless you are running Windows) 405 * the server.
345 */ 406 */
346#ifndef HAVE_CYGWIN 407#ifndef HAVE_CYGWIN
347 if (!use_privsep && getuid() != 0 && authctxt->pw && 408 if (!use_privsep && getuid() != 0 && authctxt->pw &&