summaryrefslogtreecommitdiff
path: root/auth2.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
committerDamien Miller <djm@mindrot.org>2000-10-14 16:23:11 +1100
commit874d77bb134a21a5cf625956b60173376a993ba8 (patch)
tree93dd73b2ff1fbf0ad5f3978a2c4e0d8438a0bf7c /auth2.c
parent89d9796fbedef4eed6956a2c095c7cc25330c28d (diff)
- (djm) Big OpenBSD sync:
- markus@cvs.openbsd.org 2000/09/30 10:27:44 [log.c] allow loglevel debug - markus@cvs.openbsd.org 2000/10/03 11:59:57 [packet.c] hmac->mac - markus@cvs.openbsd.org 2000/10/03 12:03:03 [auth-krb4.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c auth-rsa.c auth1.c] move fake-auth from auth1.c to individual auth methods, disables s/key in debug-msg - markus@cvs.openbsd.org 2000/10/03 12:16:48 ssh.c do not resolve canonname, i have no idea why this was added oin ossh - markus@cvs.openbsd.org 2000/10/09 15:30:44 ssh-keygen.1 ssh-keygen.c -X now reads private ssh.com DSA keys, too. - markus@cvs.openbsd.org 2000/10/09 15:32:34 auth-options.c clear options on every call. - markus@cvs.openbsd.org 2000/10/09 15:51:00 authfd.c authfd.h interop with ssh-agent2, from <res@shore.net> - markus@cvs.openbsd.org 2000/10/10 14:20:45 compat.c use rexexp for version string matching - provos@cvs.openbsd.org 2000/10/10 22:02:18 [kex.c kex.h myproposal.h ssh.h ssh2.h sshconnect2.c sshd.c dh.c dh.h] First rough implementation of the diffie-hellman group exchange. The client can ask the server for bigger groups to perform the diffie-hellman in, thus increasing the attack complexity when using ciphers with longer keys. University of Windsor provided network, T the company. - markus@cvs.openbsd.org 2000/10/11 13:59:52 [auth-rsa.c auth2.c] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:00:27 [auth-options.h] clear auth options unless auth sucessfull - markus@cvs.openbsd.org 2000/10/11 14:03:27 [scp.1 scp.c] support 'scp -o' with help from mouring@pconline.com - markus@cvs.openbsd.org 2000/10/11 14:11:35 [dh.c] Wall - markus@cvs.openbsd.org 2000/10/11 14:14:40 [auth.h auth2.c readconf.c readconf.h readpass.c servconf.c servconf.h] [ssh.h sshconnect2.c sshd_config auth2-skey.c cli.c cli.h] add support for s/key (kbd-interactive) to ssh2, based on work by mkiernan@avantgo.com and me - markus@cvs.openbsd.org 2000/10/11 14:27:24 [auth.c auth1.c auth2.c authfile.c cipher.c cipher.h kex.c kex.h] [myproposal.h packet.c readconf.c session.c ssh.c ssh.h sshconnect1.c] [sshconnect2.c sshd.c] new cipher framework - markus@cvs.openbsd.org 2000/10/11 14:45:21 [cipher.c] remove DES - markus@cvs.openbsd.org 2000/10/12 03:59:20 [cipher.c cipher.h sshconnect1.c sshconnect2.c sshd.c] enable DES in SSH-1 clients only - markus@cvs.openbsd.org 2000/10/12 08:21:13 [kex.h packet.c] remove unused - markus@cvs.openbsd.org 2000/10/13 12:34:46 [sshd.c] Kludge for F-Secure Macintosh < 1.0.2; appro@fy.chalmers.se - markus@cvs.openbsd.org 2000/10/13 12:59:15 [cipher.c cipher.h myproposal.h rijndael.c rijndael.h] rijndael/aes support - markus@cvs.openbsd.org 2000/10/13 13:10:54 [sshd.8] more info about -V - markus@cvs.openbsd.org 2000/10/13 13:12:02 [myproposal.h] prefer no compression
Diffstat (limited to 'auth2.c')
-rw-r--r--auth2.c428
1 files changed, 286 insertions, 142 deletions
diff --git a/auth2.c b/auth2.c
index 2c8c0bfdd..f34b586d4 100644
--- a/auth2.c
+++ b/auth2.c
@@ -23,7 +23,12 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $"); 26RCSID("$OpenBSD: auth2.c,v 1.19 2000/10/11 20:27:23 markus Exp $");
27
28#ifdef HAVE_OSF_SIA
29# include <sia.h>
30# include <siad.h>
31#endif
27 32
28#include <openssl/dsa.h> 33#include <openssl/dsa.h>
29#include <openssl/rsa.h> 34#include <openssl/rsa.h>
@@ -35,7 +40,6 @@ RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $");
35#include "pty.h" 40#include "pty.h"
36#include "packet.h" 41#include "packet.h"
37#include "buffer.h" 42#include "buffer.h"
38#include "cipher.h"
39#include "servconf.h" 43#include "servconf.h"
40#include "compat.h" 44#include "compat.h"
41#include "channels.h" 45#include "channels.h"
@@ -52,59 +56,85 @@ RCSID("$OpenBSD: auth2.c,v 1.16 2000/09/27 21:41:34 markus Exp $");
52#include "uidswap.h" 56#include "uidswap.h"
53#include "auth-options.h" 57#include "auth-options.h"
54 58
55#ifdef HAVE_OSF_SIA
56# include <sia.h>
57# include <siad.h>
58#endif
59
60/* import */ 59/* import */
61extern ServerOptions options; 60extern ServerOptions options;
62extern unsigned char *session_id2; 61extern unsigned char *session_id2;
63extern int session_id2_len; 62extern int session_id2_len;
64 63
64#ifdef WITH_AIXAUTHENTICATE
65extern char *aixloginmsg;
66#endif
67#ifdef HAVE_OSF_SIA
68extern int saved_argc;
69extern char **saved_argv;
70#endif
71
72static Authctxt *x_authctxt = NULL;
73static int one = 1;
74
75typedef struct Authmethod Authmethod;
76struct Authmethod {
77 char *name;
78 int (*userauth)(Authctxt *authctxt);
79 int *enabled;
80};
81
65/* protocol */ 82/* protocol */
66 83
67void input_service_request(int type, int plen, void *ctxt); 84void input_service_request(int type, int plen, void *ctxt);
68void input_userauth_request(int type, int plen, void *ctxt); 85void input_userauth_request(int type, int plen, void *ctxt);
69void protocol_error(int type, int plen, void *ctxt); 86void protocol_error(int type, int plen, void *ctxt);
70 87
71/* auth */
72int ssh2_auth_none(struct passwd *pw);
73int ssh2_auth_password(struct passwd *pw);
74int ssh2_auth_pubkey(struct passwd *pw, char *service);
75 88
76/* helper */ 89/* helper */
77struct passwd* auth_set_user(char *u, char *s); 90Authmethod *authmethod_lookup(const char *name);
91struct passwd *pwcopy(struct passwd *pw);
78int user_dsa_key_allowed(struct passwd *pw, Key *key); 92int user_dsa_key_allowed(struct passwd *pw, Key *key);
93char *authmethods_get(void);
79 94
80typedef struct Authctxt Authctxt; 95/* auth */
81struct Authctxt { 96int userauth_none(Authctxt *authctxt);
82 char *user; 97int userauth_passwd(Authctxt *authctxt);
83 char *service; 98int userauth_pubkey(Authctxt *authctxt);
84 struct passwd pw; 99int userauth_kbdint(Authctxt *authctxt);
85 int valid; 100
101Authmethod authmethods[] = {
102 {"none",
103 userauth_none,
104 &one},
105 {"publickey",
106 userauth_pubkey,
107 &options.dsa_authentication},
108 {"keyboard-interactive",
109 userauth_kbdint,
110 &options.kbd_interactive_authentication},
111 {"password",
112 userauth_passwd,
113 &options.password_authentication},
114 {NULL, NULL, NULL}
86}; 115};
87static Authctxt *authctxt = NULL;
88static int userauth_success = 0;
89 116
90/* 117/*
91 * loop until userauth_success == TRUE 118 * loop until authctxt->success == TRUE
92 */ 119 */
93 120
94void 121void
95do_authentication2() 122do_authentication2()
96{ 123{
97 /* turn off skey/kerberos, not supported by SSH2 */ 124 Authctxt *authctxt = xmalloc(sizeof(*authctxt));
98#ifdef SKEY 125 memset(authctxt, 'a', sizeof(*authctxt));
99 options.skey_authentication = 0; 126 authctxt->valid = 0;
100#endif 127 authctxt->attempt = 0;
128 authctxt->success = 0;
129 x_authctxt = authctxt; /*XXX*/
130
101#ifdef KRB4 131#ifdef KRB4
132 /* turn off kerberos, not supported by SSH2 */
102 options.kerberos_authentication = 0; 133 options.kerberos_authentication = 0;
103#endif 134#endif
104
105 dispatch_init(&protocol_error); 135 dispatch_init(&protocol_error);
106 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request); 136 dispatch_set(SSH2_MSG_SERVICE_REQUEST, &input_service_request);
107 dispatch_run(DISPATCH_BLOCK, &userauth_success, NULL); 137 dispatch_run(DISPATCH_BLOCK, &authctxt->success, authctxt);
108 do_authenticated2(); 138 do_authenticated2();
109} 139}
110 140
@@ -121,13 +151,17 @@ protocol_error(int type, int plen, void *ctxt)
121void 151void
122input_service_request(int type, int plen, void *ctxt) 152input_service_request(int type, int plen, void *ctxt)
123{ 153{
154 Authctxt *authctxt = ctxt;
124 unsigned int len; 155 unsigned int len;
125 int accept = 0; 156 int accept = 0;
126 char *service = packet_get_string(&len); 157 char *service = packet_get_string(&len);
127 packet_done(); 158 packet_done();
128 159
160 if (authctxt == NULL)
161 fatal("input_service_request: no authctxt");
162
129 if (strcmp(service, "ssh-userauth") == 0) { 163 if (strcmp(service, "ssh-userauth") == 0) {
130 if (!userauth_success) { 164 if (!authctxt->success) {
131 accept = 1; 165 accept = 1;
132 /* now we can handle user-auth requests */ 166 /* now we can handle user-auth requests */
133 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request); 167 dispatch_set(SSH2_MSG_USERAUTH_REQUEST, &input_userauth_request);
@@ -150,65 +184,99 @@ input_service_request(int type, int plen, void *ctxt)
150void 184void
151input_userauth_request(int type, int plen, void *ctxt) 185input_userauth_request(int type, int plen, void *ctxt)
152{ 186{
153 static void (*authlog) (const char *fmt,...) = verbose; 187 Authctxt *authctxt = ctxt;
154 static int attempt = 0; 188 Authmethod *m = NULL;
155 unsigned int len; 189 char *user, *service, *method;
156 int authenticated = 0; 190 int authenticated = 0;
157 char *user, *service, *method, *authmsg = NULL;
158 struct passwd *pw;
159#ifdef WITH_AIXAUTHENTICATE
160 extern char *aixloginmsg;
161#endif /* WITH_AIXAUTHENTICATE */
162 191
163 user = packet_get_string(&len); 192 if (authctxt == NULL)
164 service = packet_get_string(&len); 193 fatal("input_userauth_request: no authctxt");
165 method = packet_get_string(&len); 194 if (authctxt->attempt++ >= AUTH_FAIL_MAX) {
166 if (++attempt == AUTH_FAIL_MAX) {
167#ifdef WITH_AIXAUTHENTICATE 195#ifdef WITH_AIXAUTHENTICATE
168 loginfailed(user,get_canonical_hostname(),"ssh"); 196 loginfailed(user,get_canonical_hostname(),"ssh");
169#endif /* WITH_AIXAUTHENTICATE */ 197#endif /* WITH_AIXAUTHENTICATE */
170 packet_disconnect("too many failed userauth_requests"); 198 packet_disconnect("too many failed userauth_requests");
171 } 199 }
172 debug("userauth-request for user %s service %s method %s", user, service, method);
173 200
174 /* XXX we only allow the ssh-connection service */ 201 user = packet_get_string(NULL);
175 pw = auth_set_user(user, service); 202 service = packet_get_string(NULL);
176 if (pw && strcmp(service, "ssh-connection")==0) { 203 method = packet_get_string(NULL);
177 if (strcmp(method, "none") == 0) { 204 debug("userauth-request for user %s service %s method %s", user, service, method);
178 authenticated = ssh2_auth_none(pw); 205 debug("attempt #%d", authctxt->attempt);
179 } else if (strcmp(method, "password") == 0) { 206
180 authenticated = ssh2_auth_password(pw); 207 if (authctxt->attempt == 1) {
181 } else if (strcmp(method, "publickey") == 0) { 208 /* setup auth context */
182 authenticated = ssh2_auth_pubkey(pw, service); 209 struct passwd *pw = NULL;
210 setproctitle("%s", user);
211 pw = getpwnam(user);
212 if (pw && allowed_user(pw) && strcmp(service, "ssh-connection")==0) {
213 authctxt->pw = pwcopy(pw);
214 authctxt->valid = 1;
215 debug2("input_userauth_request: setting up authctxt for %s", user);
216#ifdef USE_PAM
217 start_pam(pw);
218#endif
219 } else {
220 log("input_userauth_request: illegal user %s", user);
221 }
222 authctxt->user = xstrdup(user);
223 authctxt->service = xstrdup(service);
224 } else if (authctxt->valid) {
225 if (strcmp(user, authctxt->user) != 0 ||
226 strcmp(service, authctxt->service) != 0) {
227 log("input_userauth_request: missmatch: (%s,%s)!=(%s,%s)",
228 user, service, authctxt->user, authctxt->service);
229 authctxt->valid = 0;
183 } 230 }
184 } 231 }
185 232
186#ifdef HAVE_CYGWIN 233 m = authmethod_lookup(method);
187 if (authenticated && !check_nt_auth(strcmp(method, "password") == 0, pw->pw_uid)) { 234 if (m != NULL) {
188 packet_disconnect("Authentication rejected for uid %d.", 235 debug2("input_userauth_request: try method %s", method);
189 (int) pw->pw_uid); 236 authenticated = m->userauth(authctxt);
237 } else {
238 debug2("input_userauth_request: unsupported method %s", method);
239 }
240 if (!authctxt->valid && authenticated == 1) {
241 log("input_userauth_request: INTERNAL ERROR: authenticated invalid user %s service %s", user, method);
190 authenticated = 0; 242 authenticated = 0;
191 } 243 }
192#endif
193 244
194 if (authenticated && pw && pw->pw_uid == 0 && !options.permit_root_login) { 245 /* Special handling for root */
246 if (authenticated == 1 &&
247 authctxt->valid && authctxt->pw->pw_uid == 0 && !options.permit_root_login) {
195 authenticated = 0; 248 authenticated = 0;
196 log("ROOT LOGIN REFUSED FROM %.200s", 249 log("ROOT LOGIN REFUSED FROM %.200s", get_canonical_hostname());
197 get_canonical_hostname());
198 } 250 }
199 251
200#ifdef USE_PAM 252#ifdef USE_PAM
201 if (authenticated && !do_pam_account(pw->pw_name, NULL)) 253 if (authenticated && !do_pam_account(authctxt->pw->pw_name, NULL))
202 authenticated = 0; 254 authenticated = 0;
203#endif /* USE_PAM */ 255#endif /* USE_PAM */
204 256
257 /* Log before sending the reply */
258 userauth_log(authctxt, authenticated, method);
259 userauth_reply(authctxt, authenticated);
260
261 xfree(service);
262 xfree(user);
263 xfree(method);
264}
265
266
267void
268userauth_log(Authctxt *authctxt, int authenticated, char *method)
269{
270 void (*authlog) (const char *fmt,...) = verbose;
271 char *user = NULL, *authmsg = NULL;
272
205 /* Raise logging level */ 273 /* Raise logging level */
206 if (authenticated == 1 || 274 if (authenticated == 1 ||
207 attempt == AUTH_FAIL_LOG || 275 !authctxt->valid ||
276 authctxt->attempt >= AUTH_FAIL_LOG ||
208 strcmp(method, "password") == 0) 277 strcmp(method, "password") == 0)
209 authlog = log; 278 authlog = log;
210 279
211 /* Log before sending the reply */
212 if (authenticated == 1) { 280 if (authenticated == 1) {
213 authmsg = "Accepted"; 281 authmsg = "Accepted";
214 } else if (authenticated == 0) { 282 } else if (authenticated == 0) {
@@ -216,18 +284,29 @@ input_userauth_request(int type, int plen, void *ctxt)
216 } else { 284 } else {
217 authmsg = "Postponed"; 285 authmsg = "Postponed";
218 } 286 }
287
288 if (authctxt->valid) {
289 user = authctxt->pw->pw_uid == 0 ? "ROOT" : authctxt->user;
290 } else {
291 user = "NOUSER";
292 }
293
219 authlog("%s %s for %.200s from %.200s port %d ssh2", 294 authlog("%s %s for %.200s from %.200s port %d ssh2",
220 authmsg, 295 authmsg,
221 method, 296 method,
222 pw && pw->pw_uid == 0 ? "ROOT" : user, 297 user,
223 get_remote_ipaddr(), 298 get_remote_ipaddr(),
224 get_remote_port()); 299 get_remote_port());
300}
225 301
302void
303userauth_reply(Authctxt *authctxt, int authenticated)
304{
226 /* XXX todo: check if multiple auth methods are needed */ 305 /* XXX todo: check if multiple auth methods are needed */
227 if (authenticated == 1) { 306 if (authenticated == 1) {
228#ifdef WITH_AIXAUTHENTICATE 307#ifdef WITH_AIXAUTHENTICATE
229 /* We don't have a pty yet, so just label the line as "ssh" */ 308 /* We don't have a pty yet, so just label the line as "ssh" */
230 if (loginsuccess(user,get_canonical_hostname(),"ssh", 309 if (loginsuccess(user, get_canonical_hostname(), "ssh",
231 &aixloginmsg) < 0) 310 &aixloginmsg) < 0)
232 aixloginmsg = NULL; 311 aixloginmsg = NULL;
233#endif /* WITH_AIXAUTHENTICATE */ 312#endif /* WITH_AIXAUTHENTICATE */
@@ -237,73 +316,106 @@ input_userauth_request(int type, int plen, void *ctxt)
237 packet_send(); 316 packet_send();
238 packet_write_wait(); 317 packet_write_wait();
239 /* now we can break out */ 318 /* now we can break out */
240 userauth_success = 1; 319 authctxt->success = 1;
241 } else if (authenticated == 0) { 320 } else if (authenticated == 0) {
321 char *methods = authmethods_get();
242 packet_start(SSH2_MSG_USERAUTH_FAILURE); 322 packet_start(SSH2_MSG_USERAUTH_FAILURE);
243 packet_put_cstring("publickey,password"); /* XXX dynamic */ 323 packet_put_cstring(methods);
244 packet_put_char(0); /* XXX partial success, unused */ 324 packet_put_char(0); /* XXX partial success, unused */
245 packet_send(); 325 packet_send();
246 packet_write_wait(); 326 packet_write_wait();
327 xfree(methods);
328 } else {
329 /* do nothing, we did already send a reply */
247 } 330 }
248
249 xfree(service);
250 xfree(user);
251 xfree(method);
252} 331}
253 332
254int 333int
255ssh2_auth_none(struct passwd *pw) 334userauth_none(Authctxt *authctxt)
256{ 335{
257#ifdef HAVE_OSF_SIA 336 /* disable method "none", only allowed one time */
258 extern int saved_argc; 337 Authmethod *m = authmethod_lookup("none");
259 extern char **saved_argv; 338 if (m != NULL)
260#endif 339 m->enabled = NULL;
261
262 packet_done(); 340 packet_done();
263 341
342 if (authctxt->valid == 0)
343 return(0);
344
345#ifdef HAVE_CYGWIN
346 if (check_nt_auth(1, authctxt->pw->pw_uid) == 0)
347 return(0);
348#endif
264#ifdef USE_PAM 349#ifdef USE_PAM
265 return auth_pam_password(pw, ""); 350 return auth_pam_password(authctxt->pw, "");
266#elif defined(HAVE_OSF_SIA) 351#elif defined(HAVE_OSF_SIA)
267 return(sia_validate_user(NULL, saved_argc, saved_argv, 352 return (sia_validate_user(NULL, saved_argc, saved_argv,
268 get_canonical_hostname(), pw->pw_name, NULL, 0, NULL, 353 get_canonical_hostname(), authctxt->pw->pw_name, NULL,
269 "") == SIASUCCESS); 354 0, NULL, "") == SIASUCCESS);
270#else /* !HAVE_OSF_SIA && !USE_PAM */ 355#else /* !HAVE_OSF_SIA && !USE_PAM */
271 return auth_password(pw, ""); 356 return auth_password(authctxt->pw, "");
272#endif /* USE_PAM */ 357#endif /* USE_PAM */
273} 358}
359
274int 360int
275ssh2_auth_password(struct passwd *pw) 361userauth_passwd(Authctxt *authctxt)
276{ 362{
277 char *password; 363 char *password;
278 int authenticated = 0; 364 int authenticated = 0;
279 int change; 365 int change;
280 unsigned int len; 366 unsigned int len;
281#ifdef HAVE_OSF_SIA
282 extern int saved_argc;
283 extern char **saved_argv;
284#endif
285 change = packet_get_char(); 367 change = packet_get_char();
286 if (change) 368 if (change)
287 log("password change not supported"); 369 log("password change not supported");
288 password = packet_get_string(&len); 370 password = packet_get_string(&len);
289 packet_done(); 371 packet_done();
290 if (options.password_authentication && 372 if (authctxt->valid &&
373#ifdef HAVE_CYGWIN
374 check_nt_auth(1, authctxt->pw->pw_uid) &&
375#endif
291#ifdef USE_PAM 376#ifdef USE_PAM
292 auth_pam_password(pw, password) == 1) 377 auth_pam_password(authctxt->pw, password) == 1)
293#elif defined(HAVE_OSF_SIA) 378#elif defined(HAVE_OSF_SIA)
294 sia_validate_user(NULL, saved_argc, saved_argv, 379 sia_validate_user(NULL, saved_argc, saved_argv,
295 get_canonical_hostname(), pw->pw_name, NULL, 0, 380 get_canonical_hostname(), authctxt->pw->pw_name, NULL, 0,
296 NULL, password) == SIASUCCESS) 381 NULL, password) == SIASUCCESS)
297#else /* !USE_PAM && !HAVE_OSF_SIA */ 382#else /* !USE_PAM && !HAVE_OSF_SIA */
298 auth_password(pw, password) == 1) 383 auth_password(authctxt->pw, password) == 1)
299#endif /* USE_PAM */ 384#endif /* USE_PAM */
300 authenticated = 1; 385 authenticated = 1;
301 memset(password, 0, len); 386 memset(password, 0, len);
302 xfree(password); 387 xfree(password);
303 return authenticated; 388 return authenticated;
304} 389}
390
391int
392userauth_kbdint(Authctxt *authctxt)
393{
394 int authenticated = 0;
395 char *lang = NULL;
396 char *devs = NULL;
397
398 lang = packet_get_string(NULL);
399 devs = packet_get_string(NULL);
400 packet_done();
401
402 debug("keyboard-interactive language %s devs %s", lang, devs);
403#ifdef SKEY
404 /* XXX hardcoded, we should look at devs */
405 if (options.skey_authentication != 0)
406 authenticated = auth2_skey(authctxt);
407#endif
408 xfree(lang);
409 xfree(devs);
410#ifdef HAVE_CYGWIN
411 if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
412 return(0);
413#endif
414 return authenticated;
415}
416
305int 417int
306ssh2_auth_pubkey(struct passwd *pw, char *service) 418userauth_pubkey(Authctxt *authctxt)
307{ 419{
308 Buffer b; 420 Buffer b;
309 Key *key; 421 Key *key;
@@ -312,15 +424,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
312 int have_sig; 424 int have_sig;
313 int authenticated = 0; 425 int authenticated = 0;
314 426
315 if (options.dsa_authentication == 0) { 427 if (!authctxt->valid) {
316 debug("pubkey auth disabled"); 428 debug2("userauth_pubkey: disabled because of invalid user");
317 return 0; 429 return 0;
318 } 430 }
319 have_sig = packet_get_char(); 431 have_sig = packet_get_char();
320 pkalg = packet_get_string(&alen); 432 pkalg = packet_get_string(&alen);
321 if (strcmp(pkalg, KEX_DSS) != 0) { 433 if (strcmp(pkalg, KEX_DSS) != 0) {
322 xfree(pkalg);
323 log("bad pkalg %s", pkalg); /*XXX*/ 434 log("bad pkalg %s", pkalg); /*XXX*/
435 xfree(pkalg);
324 return 0; 436 return 0;
325 } 437 }
326 pkblob = packet_get_string(&blen); 438 pkblob = packet_get_string(&blen);
@@ -337,11 +449,11 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
337 } 449 }
338 /* reconstruct packet */ 450 /* reconstruct packet */
339 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 451 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
340 buffer_put_cstring(&b, pw->pw_name); 452 buffer_put_cstring(&b, authctxt->user);
341 buffer_put_cstring(&b, 453 buffer_put_cstring(&b,
342 datafellows & SSH_BUG_PUBKEYAUTH ? 454 datafellows & SSH_BUG_PUBKEYAUTH ?
343 "ssh-userauth" : 455 "ssh-userauth" :
344 service); 456 authctxt->service);
345 buffer_put_cstring(&b, "publickey"); 457 buffer_put_cstring(&b, "publickey");
346 buffer_put_char(&b, have_sig); 458 buffer_put_char(&b, have_sig);
347 buffer_put_cstring(&b, KEX_DSS); 459 buffer_put_cstring(&b, KEX_DSS);
@@ -350,15 +462,15 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
350 buffer_dump(&b); 462 buffer_dump(&b);
351#endif 463#endif
352 /* test for correct signature */ 464 /* test for correct signature */
353 if (user_dsa_key_allowed(pw, key) && 465 if (user_dsa_key_allowed(authctxt->pw, key) &&
354 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1) 466 dsa_verify(key, sig, slen, buffer_ptr(&b), buffer_len(&b)) == 1)
355 authenticated = 1; 467 authenticated = 1;
356 buffer_clear(&b); 468 buffer_clear(&b);
357 xfree(sig); 469 xfree(sig);
358 } else { 470 } else {
471 debug("test whether pkalg/pkblob are acceptable");
359 packet_done(); 472 packet_done();
360 debug("test key..."); 473
361 /* test whether pkalg/pkblob are acceptable */
362 /* XXX fake reply and always send PK_OK ? */ 474 /* XXX fake reply and always send PK_OK ? */
363 /* 475 /*
364 * XXX this allows testing whether a user is allowed 476 * XXX this allows testing whether a user is allowed
@@ -367,7 +479,7 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
367 * if a user is not allowed to login. is this an 479 * if a user is not allowed to login. is this an
368 * issue? -markus 480 * issue? -markus
369 */ 481 */
370 if (user_dsa_key_allowed(pw, key)) { 482 if (user_dsa_key_allowed(authctxt->pw, key)) {
371 packet_start(SSH2_MSG_USERAUTH_PK_OK); 483 packet_start(SSH2_MSG_USERAUTH_PK_OK);
372 packet_put_string(pkalg, alen); 484 packet_put_string(pkalg, alen);
373 packet_put_string(pkblob, blen); 485 packet_put_string(pkblob, blen);
@@ -376,61 +488,73 @@ ssh2_auth_pubkey(struct passwd *pw, char *service)
376 authenticated = -1; 488 authenticated = -1;
377 } 489 }
378 } 490 }
491 if (authenticated != 1)
492 auth_clear_options();
379 key_free(key); 493 key_free(key);
380 } 494 }
381 xfree(pkalg); 495 xfree(pkalg);
382 xfree(pkblob); 496 xfree(pkblob);
497#ifdef HAVE_CYGWIN
498 if (check_nt_auth(0, authctxt->pw->pw_uid) == 0)
499 return(0);
500#endif
383 return authenticated; 501 return authenticated;
384} 502}
385 503
386/* set and get current user */ 504/* get current user */
387 505
388struct passwd* 506struct passwd*
389auth_get_user(void) 507auth_get_user(void)
390{ 508{
391 return (authctxt != NULL && authctxt->valid) ? &authctxt->pw : NULL; 509 return (x_authctxt != NULL && x_authctxt->valid) ? x_authctxt->pw : NULL;
392} 510}
393 511
394struct passwd* 512#define DELIM ","
395auth_set_user(char *u, char *s) 513
514char *
515authmethods_get(void)
396{ 516{
397 struct passwd *pw, *copy; 517 Authmethod *method = NULL;
398 518 unsigned int size = 0;
399 if (authctxt == NULL) { 519 char *list;
400 authctxt = xmalloc(sizeof(*authctxt)); 520
401 authctxt->valid = 0; 521 for (method = authmethods; method->name != NULL; method++) {
402 authctxt->user = xstrdup(u); 522 if (strcmp(method->name, "none") == 0)
403 authctxt->service = xstrdup(s); 523 continue;
404 setproctitle("%s", u); 524 if (method->enabled != NULL && *(method->enabled) != 0) {
405 pw = getpwnam(u); 525 if (size != 0)
406 if (!pw || !allowed_user(pw)) { 526 size += strlen(DELIM);
407 log("auth_set_user: illegal user %s", u); 527 size += strlen(method->name);
408 return NULL;
409 } 528 }
410#ifdef USE_PAM 529 }
411 start_pam(pw); 530 size++; /* trailing '\0' */
412#endif 531 list = xmalloc(size);
413 copy = &authctxt->pw; 532 list[0] = '\0';
414 memset(copy, 0, sizeof(*copy)); 533
415 copy->pw_name = xstrdup(pw->pw_name); 534 for (method = authmethods; method->name != NULL; method++) {
416 copy->pw_passwd = xstrdup(pw->pw_passwd); 535 if (strcmp(method->name, "none") == 0)
417 copy->pw_uid = pw->pw_uid; 536 continue;
418 copy->pw_gid = pw->pw_gid; 537 if (method->enabled != NULL && *(method->enabled) != 0) {
419#ifdef HAVE_PW_CLASS_IN_PASSWD 538 if (list[0] != '\0')
420 copy->pw_class = xstrdup(pw->pw_class); 539 strlcat(list, DELIM, size);
421#endif 540 strlcat(list, method->name, size);
422 copy->pw_dir = xstrdup(pw->pw_dir);
423 copy->pw_shell = xstrdup(pw->pw_shell);
424 authctxt->valid = 1;
425 } else {
426 if (strcmp(u, authctxt->user) != 0 ||
427 strcmp(s, authctxt->service) != 0) {
428 log("auth_set_user: missmatch: (%s,%s)!=(%s,%s)",
429 u, s, authctxt->user, authctxt->service);
430 return NULL;
431 } 541 }
432 } 542 }
433 return auth_get_user(); 543 return list;
544}
545
546Authmethod *
547authmethod_lookup(const char *name)
548{
549 Authmethod *method = NULL;
550 if (name != NULL)
551 for (method = authmethods; method->name != NULL; method++)
552 if (method->enabled != NULL &&
553 *(method->enabled) != 0 &&
554 strcmp(name, method->name) == 0)
555 return method;
556 debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
557 return NULL;
434} 558}
435 559
436/* return 1 if user allows given key */ 560/* return 1 if user allows given key */
@@ -445,6 +569,9 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
445 struct stat st; 569 struct stat st;
446 Key *found; 570 Key *found;
447 571
572 if (pw == NULL)
573 return 0;
574
448 /* Temporarily use the user's uid. */ 575 /* Temporarily use the user's uid. */
449 temporarily_use_uid(pw->pw_uid); 576 temporarily_use_uid(pw->pw_uid);
450 577
@@ -550,3 +677,20 @@ user_dsa_key_allowed(struct passwd *pw, Key *key)
550 key_free(found); 677 key_free(found);
551 return found_key; 678 return found_key;
552} 679}
680
681struct passwd *
682pwcopy(struct passwd *pw)
683{
684 struct passwd *copy = xmalloc(sizeof(*copy));
685 memset(copy, 0, sizeof(*copy));
686 copy->pw_name = xstrdup(pw->pw_name);
687 copy->pw_passwd = xstrdup(pw->pw_passwd);
688 copy->pw_uid = pw->pw_uid;
689 copy->pw_gid = pw->pw_gid;
690#ifdef HAVE_PW_CLASS_IN_PASSWD
691 copy->pw_class = xstrdup(pw->pw_class);
692#endif
693 copy->pw_dir = xstrdup(pw->pw_dir);
694 copy->pw_shell = xstrdup(pw->pw_shell);
695 return copy;
696}