source: trunk/third/openssh/sshconnect2.c @ 17193

Revision 17193, 31.6 KB checked in by zacheiss, 22 years ago (diff)
GSSAPI support for v2 of the ssh protocol.
Line 
1/*
2 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.85 2001/11/07 16:03:17 markus Exp $");
27
28#include <openssl/bn.h>
29#include <openssl/md5.h>
30#include <openssl/dh.h>
31#include <openssl/hmac.h>
32
33#include "ssh.h"
34#include "ssh2.h"
35#include "xmalloc.h"
36#include "rsa.h"
37#include "buffer.h"
38#include "packet.h"
39#include "uidswap.h"
40#include "compat.h"
41#include "bufaux.h"
42#include "cipher.h"
43#include "kex.h"
44#include "myproposal.h"
45#include "key.h"
46#include "sshconnect.h"
47#include "authfile.h"
48#include "dh.h"
49#include "authfd.h"
50#include "log.h"
51#include "readconf.h"
52#include "readpass.h"
53#include "match.h"
54#include "dispatch.h"
55#include "canohost.h"
56
57#ifdef GSSAPI
58#include "ssh-gss.h"
59#endif
60
61/* import */
62extern char *client_version_string;
63extern char *server_version_string;
64extern Options options;
65
66/*
67 * SSH2 key exchange
68 */
69
70u_char *session_id2 = NULL;
71int session_id2_len = 0;
72
73char *xxx_host;
74struct sockaddr *xxx_hostaddr;
75
76Kex *xxx_kex = NULL;
77
78static int
79verify_host_key_callback(Key *hostkey)
80{
81        if (verify_host_key(xxx_host, xxx_hostaddr, hostkey) == -1)
82                fatal("Host key verification failed.");
83        return 0;
84}
85
86void
87ssh_kex2(char *host, struct sockaddr *hostaddr)
88{
89        Kex *kex;
90
91        xxx_host = host;
92        xxx_hostaddr = hostaddr;
93
94#ifdef GSSAPI
95        /* This is a bit of a nasty kludge. This adds the GSSAPI included
96         * key exchange methods to the top of the list, allowing the GSSAPI
97         * code to decide whether each one should be included or not.
98         */     
99        {
100                char *orig, *gss;
101                int len;
102                orig = myproposal[PROPOSAL_KEX_ALGS];
103                gss = ssh_gssapi_mechanisms(0,host);
104                if (gss) {
105                   len = strlen(orig)+strlen(gss)+2;
106                   myproposal[PROPOSAL_KEX_ALGS]=xmalloc(len);
107                   snprintf(myproposal[PROPOSAL_KEX_ALGS],len,"%s,%s",gss,orig);
108                   /* If we've got GSSAPI algorithms, then we also support the
109                    * 'null' hostkey, as a last resort */
110                   orig=myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
111                   len = strlen(orig)+sizeof(",null");
112                   myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]=xmalloc(len);
113                   snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],len,"%s,null",orig); 
114                }
115        }
116#endif
117
118        if (options.ciphers == (char *)-1) {
119                log("No valid ciphers for protocol version 2 given, using defaults.");
120                options.ciphers = NULL;
121        }
122        if (options.ciphers != NULL) {
123                myproposal[PROPOSAL_ENC_ALGS_CTOS] =
124                myproposal[PROPOSAL_ENC_ALGS_STOC] = options.ciphers;
125        }
126        myproposal[PROPOSAL_ENC_ALGS_CTOS] =
127            compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_CTOS]);
128        myproposal[PROPOSAL_ENC_ALGS_STOC] =
129            compat_cipher_proposal(myproposal[PROPOSAL_ENC_ALGS_STOC]);
130        if (options.compression) {
131                myproposal[PROPOSAL_COMP_ALGS_CTOS] =
132                myproposal[PROPOSAL_COMP_ALGS_STOC] = "zlib";
133        } else {
134                myproposal[PROPOSAL_COMP_ALGS_CTOS] =
135                myproposal[PROPOSAL_COMP_ALGS_STOC] = "none";
136        }
137        if (options.macs != NULL) {
138                myproposal[PROPOSAL_MAC_ALGS_CTOS] =
139                myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
140        }
141        if (options.hostkeyalgorithms != NULL)
142                myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
143                    options.hostkeyalgorithms;
144
145        /* start key exchange */
146        kex = kex_setup(myproposal);
147        kex->client_version_string=client_version_string;
148        kex->server_version_string=server_version_string;
149        kex->verify_host_key=&verify_host_key_callback;
150        kex->host=host;
151
152#ifdef GSSAPI
153        kex->options.gss_deleg_creds=options.gss_deleg_creds;
154#endif
155
156        xxx_kex = kex;
157
158        dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
159
160        session_id2 = kex->session_id;
161        session_id2_len = kex->session_id_len;
162
163#ifdef DEBUG_KEXDH
164        /* send 1st encrypted/maced/compressed message */
165        packet_start(SSH2_MSG_IGNORE);
166        packet_put_cstring("markus");
167        packet_send();
168        packet_write_wait();
169#endif
170        debug("done: ssh_kex2.");
171}
172
173/*
174 * Authenticate user
175 */
176
177typedef struct Authctxt Authctxt;
178typedef struct Authmethod Authmethod;
179
180typedef int sign_cb_fn(
181    Authctxt *authctxt, Key *key,
182    u_char **sigp, int *lenp, u_char *data, int datalen);
183
184struct Authctxt {
185        const char *server_user;
186        const char *local_user;
187        const char *host;
188        const char *service;
189        Authmethod *method;
190        int success;
191        char *authlist;
192        /* pubkey */
193        Key *last_key;
194        sign_cb_fn *last_key_sign;
195        int last_key_hint;
196        AuthenticationConnection *agent;
197        /* hostbased */
198        Key **keys;
199        int nkeys;
200        /* kbd-interactive */
201        int info_req_seen;
202        /* generic */
203        void *methoddata;
204};
205struct Authmethod {
206        char    *name;          /* string to compare against server's list */
207        int     (*userauth)(Authctxt *authctxt);
208        int     *enabled;       /* flag in option struct that enables method */
209        int     *batch_flag;    /* flag in option struct that disables method */
210};
211
212void    input_userauth_success(int type, int plen, void *ctxt);
213void    input_userauth_failure(int type, int plen, void *ctxt);
214void    input_userauth_banner(int type, int plen, void *ctxt);
215void    input_userauth_error(int type, int plen, void *ctxt);
216void    input_userauth_info_req(int type, int plen, void *ctxt);
217void    input_userauth_pk_ok(int type, int plen, void *ctxt);
218
219int     userauth_none(Authctxt *authctxt);
220int     userauth_pubkey(Authctxt *authctxt);
221int     userauth_passwd(Authctxt *authctxt);
222int     userauth_kbdint(Authctxt *authctxt);
223int     userauth_hostbased(Authctxt *authctxt);
224
225#ifdef GSSAPI
226int     userauth_external(Authctxt *authctxt);
227int     userauth_gssapi(Authctxt *authctxt);
228void    input_gssapi_response(int type, int plen, void *ctxt);
229void    input_gssapi_token(int type, int plen, void *ctxt);
230void    input_gssapi_hash(int type, int plen, void *ctxt);
231
232int     gss_host_key_ok=0;
233#endif
234
235void    userauth(Authctxt *authctxt, char *authlist);
236
237static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *);
238static void clear_auth_state(Authctxt *);
239
240static Authmethod *authmethod_get(char *authlist);
241static Authmethod *authmethod_lookup(const char *name);
242static char *authmethods_get(void);
243
244Authmethod authmethods[] = {
245#ifdef GSSAPI
246        {"external-keyx",
247                userauth_external,
248                &options.gss_authentication,
249                NULL},
250        {"gssapi",
251                userauth_gssapi,
252                &options.gss_authentication,
253                NULL},
254#endif
255        {"hostbased",
256                userauth_hostbased,
257                &options.hostbased_authentication,
258                NULL},
259        {"publickey",
260                userauth_pubkey,
261                &options.pubkey_authentication,
262                NULL},
263        {"keyboard-interactive",
264                userauth_kbdint,
265                &options.kbd_interactive_authentication,
266                &options.batch_mode},
267        {"password",
268                userauth_passwd,
269                &options.password_authentication,
270                &options.batch_mode},
271        {"none",
272                userauth_none,
273                NULL,
274                NULL},
275        {NULL, NULL, NULL, NULL}
276};
277
278void
279ssh_userauth2(const char *local_user, const char *server_user, char *host,
280    Key **keys, int nkeys)
281{
282        Authctxt authctxt;
283        int type;
284        int plen;
285
286        if (options.challenge_response_authentication)
287                options.kbd_interactive_authentication = 1;
288
289        debug("send SSH2_MSG_SERVICE_REQUEST");
290        packet_start(SSH2_MSG_SERVICE_REQUEST);
291        packet_put_cstring("ssh-userauth");
292        packet_send();
293        packet_write_wait();
294        type = packet_read(&plen);
295        if (type != SSH2_MSG_SERVICE_ACCEPT) {
296                fatal("denied SSH2_MSG_SERVICE_ACCEPT: %d", type);
297        }
298        if (packet_remaining() > 0) {
299                char *reply = packet_get_string(&plen);
300                debug("service_accept: %s", reply);
301                xfree(reply);
302        } else {
303                debug("buggy server: service_accept w/o service");
304        }
305        packet_done();
306        debug("got SSH2_MSG_SERVICE_ACCEPT");
307
308        if (options.preferred_authentications == NULL)
309                options.preferred_authentications = authmethods_get();
310
311        /* setup authentication context */
312        memset(&authctxt, 0, sizeof(authctxt));
313        authctxt.agent = ssh_get_authentication_connection();
314        authctxt.server_user = server_user;
315        authctxt.local_user = local_user;
316        authctxt.host = host;
317        authctxt.service = "ssh-connection";            /* service name */
318        authctxt.success = 0;
319        authctxt.method = authmethod_lookup("none");
320        authctxt.authlist = NULL;
321        authctxt.methoddata = NULL;
322        authctxt.keys = keys;
323        authctxt.nkeys = nkeys;
324        authctxt.info_req_seen = 0;
325        if (authctxt.method == NULL)
326                fatal("ssh_userauth2: internal error: cannot send userauth none request");
327
328        /* initial userauth request */
329        userauth_none(&authctxt);
330
331        dispatch_init(&input_userauth_error);
332        dispatch_set(SSH2_MSG_USERAUTH_SUCCESS, &input_userauth_success);
333        dispatch_set(SSH2_MSG_USERAUTH_FAILURE, &input_userauth_failure);
334        dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
335        dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt);     /* loop until success */
336
337        if (authctxt.agent != NULL)
338                ssh_close_authentication_connection(authctxt.agent);
339
340        debug("ssh-userauth2 successful: method %s", authctxt.method->name);
341}
342void
343userauth(Authctxt *authctxt, char *authlist)
344{
345        if (authctxt->methoddata!=NULL) {
346                xfree(authctxt->methoddata);
347                authctxt->methoddata=NULL;
348        }
349           
350        if (authlist == NULL) {
351                authlist = authctxt->authlist;
352        } else {
353                if (authctxt->authlist)
354                        xfree(authctxt->authlist);
355                authctxt->authlist = authlist;
356        }
357        for (;;) {
358                Authmethod *method = authmethod_get(authlist);
359                if (method == NULL)
360                        fatal("Permission denied (%s).", authlist);
361                authctxt->method = method;
362                if (method->userauth(authctxt) != 0) {
363                        debug2("we sent a %s packet, wait for reply", method->name);
364                        break;
365                } else {
366                        debug2("we did not send a packet, disable method");
367                        method->enabled = NULL;
368                }
369        }
370}
371void
372input_userauth_error(int type, int plen, void *ctxt)
373{
374        fatal("input_userauth_error: bad message during authentication: "
375           "type %d", type);
376}
377void
378input_userauth_banner(int type, int plen, void *ctxt)
379{
380        char *msg, *lang;
381        debug3("input_userauth_banner");
382        msg = packet_get_string(NULL);
383        lang = packet_get_string(NULL);
384        fprintf(stderr, "%s", msg);
385        xfree(msg);
386        xfree(lang);
387}
388void
389input_userauth_success(int type, int plen, void *ctxt)
390{
391        Authctxt *authctxt = ctxt;
392        if (authctxt == NULL)
393                fatal("input_userauth_success: no authentication context");
394        if (authctxt->authlist)
395                xfree(authctxt->authlist);
396        if (authctxt->methoddata)
397                xfree(authctxt->methoddata);
398        clear_auth_state(authctxt);
399        authctxt->success = 1;                  /* break out */
400}
401void
402input_userauth_failure(int type, int plen, void *ctxt)
403{
404        Authctxt *authctxt = ctxt;
405        char *authlist = NULL;
406        int partial;
407
408        if (authctxt == NULL)
409                fatal("input_userauth_failure: no authentication context");
410
411        authlist = packet_get_string(NULL);
412        partial = packet_get_char();
413        packet_done();
414
415        if (partial != 0)
416                log("Authenticated with partial success.");
417        debug("authentications that can continue: %s", authlist);
418
419        clear_auth_state(authctxt);
420        userauth(authctxt, authlist);
421}
422void
423input_userauth_pk_ok(int type, int plen, void *ctxt)
424{
425        Authctxt *authctxt = ctxt;
426        Key *key = NULL;
427        Buffer b;
428        int alen, blen, sent = 0;
429        char *pkalg, *pkblob, *fp;
430
431        if (authctxt == NULL)
432                fatal("input_userauth_pk_ok: no authentication context");
433        if (datafellows & SSH_BUG_PKOK) {
434                /* this is similar to SSH_BUG_PKAUTH */
435                debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
436                pkblob = packet_get_string(&blen);
437                buffer_init(&b);
438                buffer_append(&b, pkblob, blen);
439                pkalg = buffer_get_string(&b, &alen);
440                buffer_free(&b);
441        } else {
442                pkalg = packet_get_string(&alen);
443                pkblob = packet_get_string(&blen);
444        }
445        packet_done();
446
447        debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d",
448            pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
449
450        do {
451                if (authctxt->last_key == NULL ||
452                    authctxt->last_key_sign == NULL) {
453                        debug("no last key or no sign cb");
454                        break;
455                }
456                if (key_type_from_name(pkalg) == KEY_UNSPEC) {
457                        debug("unknown pkalg %s", pkalg);
458                        break;
459                }
460                if ((key = key_from_blob(pkblob, blen)) == NULL) {
461                        debug("no key from blob. pkalg %s", pkalg);
462                        break;
463                }
464                fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
465                debug2("input_userauth_pk_ok: fp %s", fp);
466                xfree(fp);
467                if (!key_equal(key, authctxt->last_key)) {
468                        debug("key != last_key");
469                        break;
470                }
471                sent = sign_and_send_pubkey(authctxt, key,
472                   authctxt->last_key_sign);
473        } while(0);
474
475        if (key != NULL)
476                key_free(key);
477        xfree(pkalg);
478        xfree(pkblob);
479
480        /* unregister */
481        clear_auth_state(authctxt);
482        dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
483
484        /* try another method if we did not send a packet*/
485        if (sent == 0)
486                userauth(authctxt, NULL);
487
488}
489
490#ifdef GSSAPI
491int
492userauth_gssapi(Authctxt *authctxt)
493{
494        int i;
495        Gssctxt *gssctxt;
496        static int tries=0;
497
498        /* For now, we only make one attempt at this. We could try offering
499         * the server different GSSAPI OIDs until we get bored, I suppose.
500         */     
501        if (tries++>0) return 0;
502
503        gssctxt=xmalloc(sizeof(Gssctxt));
504
505        /* Initialise as much of our context as we can, so failures can be
506         * trapped before sending any packets.
507         */
508        ssh_gssapi_build_ctx(gssctxt);
509        if (ssh_gssapi_import_name(gssctxt,authctxt->host)) {
510                return(0);
511        }
512        authctxt->methoddata=(void *)gssctxt;
513               
514        packet_start(SSH2_MSG_USERAUTH_REQUEST);
515        packet_put_cstring(authctxt->server_user);
516        packet_put_cstring(authctxt->service);
517        packet_put_cstring(authctxt->method->name);
518
519        /* FIXME: This assumes that our current GSSAPI implementation
520         * supports all of the mechanisms listed in supported_mechs.
521         * This may not be the case - we should use something along
522         * the lines of the code in gss_genr to remove the ones that
523         * aren't supported */
524        packet_put_int(GSS_LAST_ENTRY);
525        for (i=0;i<GSS_LAST_ENTRY;i++) {
526                packet_put_string(supported_mechs[i].oid.elements,
527                                  supported_mechs[i].oid.length);
528        }
529        packet_send();
530        packet_write_wait();
531
532        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE,&input_gssapi_response);
533        dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN,&input_gssapi_token);
534       
535        return 1;
536}
537
538void
539input_gssapi_response(int type, int plen, void *ctxt)
540{
541        Authctxt *authctxt = ctxt;
542        Gssctxt *gssctxt;
543        OM_uint32 status,ms;
544        int oidlen;
545        char *oidv;
546        gss_buffer_desc send_tok;
547       
548        if (authctxt == NULL)
549                fatal("input_gssapi_response: no authentication context");
550        gssctxt = authctxt->methoddata;
551       
552        /* Setup our OID */
553        oidv=packet_get_string(&oidlen);
554        ssh_gssapi_set_oid_data(gssctxt,oidv,oidlen);
555       
556        packet_done();
557       
558        status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
559                                     GSS_C_NO_BUFFER, &send_tok,
560                                     NULL);
561        if (GSS_ERROR(status)) {
562                /* Start again with next method on list */
563                debug("Trying to start again");
564                userauth(authctxt,NULL);
565                return;
566        }
567
568        /* We must have data to send */                                 
569        packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
570        packet_put_string(send_tok.value,send_tok.length);
571        packet_send();
572        packet_write_wait();
573        gss_release_buffer(&ms, &send_tok);
574}
575
576void
577input_gssapi_token(int type, int plen, void *ctxt)
578{
579        Authctxt *authctxt = ctxt;
580        Gssctxt *gssctxt;
581        gss_buffer_desc send_tok,recv_tok;
582        OM_uint32 status;
583       
584        if (authctxt == NULL)
585                fatal("input_gssapi_response: no authentication context");
586        gssctxt = authctxt->methoddata;
587       
588        recv_tok.value=packet_get_string(&recv_tok.length);
589
590        status=ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds,
591                                   &recv_tok, &send_tok, NULL);
592
593        packet_done();
594       
595        if (GSS_ERROR(status)) {
596                /* Start again with the next method in the list */
597                userauth(authctxt,NULL);
598                return;
599        }
600       
601        if (send_tok.length>0) {
602                packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN);
603                packet_put_string(send_tok.value,send_tok.length);
604                packet_send();
605                packet_write_wait();
606        }
607       
608        if (status == GSS_S_COMPLETE) {
609                /* If that succeeded, send a exchange complete message */
610                packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
611                packet_send();
612                packet_write_wait();
613        }
614}
615
616int
617userauth_external(Authctxt *authctxt)
618{
619        static int attempt =0;
620       
621        if (attempt++ >= 1)
622                return 0;
623                               
624        debug2("userauth_external");
625        packet_start(SSH2_MSG_USERAUTH_REQUEST);
626        packet_put_cstring(authctxt->server_user);
627        packet_put_cstring(authctxt->service);
628        packet_put_cstring(authctxt->method->name);
629        packet_send();
630        packet_write_wait();
631        return 1;
632}                                                                                               
633#endif /* GSSAPI */
634
635int
636userauth_none(Authctxt *authctxt)
637{
638        /* initial userauth request */
639        packet_start(SSH2_MSG_USERAUTH_REQUEST);
640        packet_put_cstring(authctxt->server_user);
641        packet_put_cstring(authctxt->service);
642        packet_put_cstring(authctxt->method->name);
643        packet_send();
644        return 1;
645
646}
647
648int
649userauth_passwd(Authctxt *authctxt)
650{
651        static int attempt = 0;
652        char prompt[80];
653        char *password;
654
655        if (attempt++ >= options.number_of_password_prompts)
656                return 0;
657
658        if(attempt != 1)
659                error("Permission denied, please try again.");
660
661        snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
662            authctxt->server_user, authctxt->host);
663        password = read_passphrase(prompt, 0);
664        packet_start(SSH2_MSG_USERAUTH_REQUEST);
665        packet_put_cstring(authctxt->server_user);
666        packet_put_cstring(authctxt->service);
667        packet_put_cstring(authctxt->method->name);
668        packet_put_char(0);
669        packet_put_cstring(password);
670        memset(password, 0, strlen(password));
671        xfree(password);
672        packet_add_padding(64);
673        packet_send();
674        return 1;
675}
676
677static void
678clear_auth_state(Authctxt *authctxt)
679{
680        /* XXX clear authentication state */
681        if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
682                debug3("clear_auth_state: key_free %p", authctxt->last_key);
683                key_free(authctxt->last_key);
684        }
685        authctxt->last_key = NULL;
686        authctxt->last_key_hint = -2;
687        authctxt->last_key_sign = NULL;
688}
689
690static int
691sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
692{
693        Buffer b;
694        u_char *blob, *signature;
695        int bloblen, slen;
696        int skip = 0;
697        int ret = -1;
698        int have_sig = 1;
699
700        debug3("sign_and_send_pubkey");
701
702        if (key_to_blob(k, &blob, &bloblen) == 0) {
703                /* we cannot handle this key */
704                debug3("sign_and_send_pubkey: cannot handle key");
705                return 0;
706        }
707        /* data to be signed */
708        buffer_init(&b);
709        if (datafellows & SSH_OLD_SESSIONID) {
710                buffer_append(&b, session_id2, session_id2_len);
711                skip = session_id2_len;
712        } else {
713                buffer_put_string(&b, session_id2, session_id2_len);
714                skip = buffer_len(&b);
715        }
716        buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
717        buffer_put_cstring(&b, authctxt->server_user);
718        buffer_put_cstring(&b,
719            datafellows & SSH_BUG_PKSERVICE ?
720            "ssh-userauth" :
721            authctxt->service);
722        if (datafellows & SSH_BUG_PKAUTH) {
723                buffer_put_char(&b, have_sig);
724        } else {
725                buffer_put_cstring(&b, authctxt->method->name);
726                buffer_put_char(&b, have_sig);
727                buffer_put_cstring(&b, key_ssh_name(k));
728        }
729        buffer_put_string(&b, blob, bloblen);
730
731        /* generate signature */
732        ret = (*sign_callback)(authctxt, k, &signature, &slen,
733            buffer_ptr(&b), buffer_len(&b));
734        if (ret == -1) {
735                xfree(blob);
736                buffer_free(&b);
737                return 0;
738        }
739#ifdef DEBUG_PK
740        buffer_dump(&b);
741#endif
742        if (datafellows & SSH_BUG_PKSERVICE) {
743                buffer_clear(&b);
744                buffer_append(&b, session_id2, session_id2_len);
745                skip = session_id2_len;
746                buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
747                buffer_put_cstring(&b, authctxt->server_user);
748                buffer_put_cstring(&b, authctxt->service);
749                buffer_put_cstring(&b, authctxt->method->name);
750                buffer_put_char(&b, have_sig);
751                if (!(datafellows & SSH_BUG_PKAUTH))
752                        buffer_put_cstring(&b, key_ssh_name(k));
753                buffer_put_string(&b, blob, bloblen);
754        }
755        xfree(blob);
756
757        /* append signature */
758        buffer_put_string(&b, signature, slen);
759        xfree(signature);
760
761        /* skip session id and packet type */
762        if (buffer_len(&b) < skip + 1)
763                fatal("userauth_pubkey: internal error");
764        buffer_consume(&b, skip + 1);
765
766        /* put remaining data from buffer into packet */
767        packet_start(SSH2_MSG_USERAUTH_REQUEST);
768        packet_put_raw(buffer_ptr(&b), buffer_len(&b));
769        buffer_free(&b);
770        packet_send();
771
772        return 1;
773}
774
775static int
776send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
777    int hint)
778{
779        u_char *blob;
780        int bloblen, have_sig = 0;
781
782        debug3("send_pubkey_test");
783
784        if (key_to_blob(k, &blob, &bloblen) == 0) {
785                /* we cannot handle this key */
786                debug3("send_pubkey_test: cannot handle key");
787                return 0;
788        }
789        /* register callback for USERAUTH_PK_OK message */
790        authctxt->last_key_sign = sign_callback;
791        authctxt->last_key_hint = hint;
792        authctxt->last_key = k;
793        dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
794
795        packet_start(SSH2_MSG_USERAUTH_REQUEST);
796        packet_put_cstring(authctxt->server_user);
797        packet_put_cstring(authctxt->service);
798        packet_put_cstring(authctxt->method->name);
799        packet_put_char(have_sig);
800        if (!(datafellows & SSH_BUG_PKAUTH))
801                packet_put_cstring(key_ssh_name(k));
802        packet_put_string(blob, bloblen);
803        xfree(blob);
804        packet_send();
805        return 1;
806}
807
808static Key *
809load_identity_file(char *filename)
810{
811        Key *private;
812        char prompt[300], *passphrase;
813        int quit, i;
814        struct stat st;
815
816        if (stat(filename, &st) < 0) {
817                debug3("no such identity: %s", filename);
818                return NULL;
819        }
820        private = key_load_private_type(KEY_UNSPEC, filename, "", NULL);
821        if (private == NULL) {
822                if (options.batch_mode)
823                        return NULL;
824                snprintf(prompt, sizeof prompt,
825                     "Enter passphrase for key '%.100s': ", filename);
826                for (i = 0; i < options.number_of_password_prompts; i++) {
827                        passphrase = read_passphrase(prompt, 0);
828                        if (strcmp(passphrase, "") != 0) {
829                                private = key_load_private_type(KEY_UNSPEC, filename,
830                                    passphrase, NULL);
831                                quit = 0;
832                        } else {
833                                debug2("no passphrase given, try next key");
834                                quit = 1;
835                        }
836                        memset(passphrase, 0, strlen(passphrase));
837                        xfree(passphrase);
838                        if (private != NULL || quit)
839                                break;
840                        debug2("bad passphrase given, try again...");
841                }
842        }
843        return private;
844}
845
846static int
847identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
848    u_char *data, int datalen)
849{
850        Key *private;
851        int idx, ret;
852
853        idx = authctxt->last_key_hint;
854        if (idx < 0)
855                return -1;
856
857        /* private key is stored in external hardware */
858        if (options.identity_keys[idx]->flags & KEY_FLAG_EXT)
859                return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen);
860
861        private = load_identity_file(options.identity_files[idx]);
862        if (private == NULL)
863                return -1;
864        ret = key_sign(private, sigp, lenp, data, datalen);
865        key_free(private);
866        return ret;
867}
868
869static int
870agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
871    u_char *data, int datalen)
872{
873        return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
874}
875
876static int
877key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
878    u_char *data, int datalen)
879{
880        return key_sign(key, sigp, lenp, data, datalen);
881}
882
883static int
884userauth_pubkey_agent(Authctxt *authctxt)
885{
886        static int called = 0;
887        int ret = 0;
888        char *comment;
889        Key *k;
890
891        if (called == 0) {
892                if (ssh_get_num_identities(authctxt->agent, 2) == 0)
893                        debug2("userauth_pubkey_agent: no keys at all");
894                called = 1;
895        }
896        k = ssh_get_next_identity(authctxt->agent, &comment, 2);
897        if (k == NULL) {
898                debug2("userauth_pubkey_agent: no more keys");
899        } else {
900                debug("userauth_pubkey_agent: testing agent key %s", comment);
901                xfree(comment);
902                ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
903                if (ret == 0)
904                        key_free(k);
905        }
906        if (ret == 0)
907                debug2("userauth_pubkey_agent: no message sent");
908        return ret;
909}
910
911int
912userauth_pubkey(Authctxt *authctxt)
913{
914        static int idx = 0;
915        int sent = 0;
916        Key *key;
917        char *filename;
918
919        if (authctxt->agent != NULL) {
920                do {
921                        sent = userauth_pubkey_agent(authctxt);
922                } while(!sent && authctxt->agent->howmany > 0);
923        }
924        while (!sent && idx < options.num_identity_files) {
925                key = options.identity_keys[idx];
926                filename = options.identity_files[idx];
927                if (key == NULL) {
928                        debug("try privkey: %s", filename);
929                        key = load_identity_file(filename);
930                        if (key != NULL) {
931                                sent = sign_and_send_pubkey(authctxt, key,
932                                    key_sign_cb);
933                                key_free(key);
934                        }
935                } else if (key->type != KEY_RSA1) {
936                        debug("try pubkey: %s", filename);
937                        sent = send_pubkey_test(authctxt, key,
938                            identity_sign_cb, idx);
939                }
940                idx++;
941        }
942        return sent;
943}
944
945/*
946 * Send userauth request message specifying keyboard-interactive method.
947 */
948int
949userauth_kbdint(Authctxt *authctxt)
950{
951        static int attempt = 0;
952
953        if (attempt++ >= options.number_of_password_prompts)
954                return 0;
955        /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */
956        if (attempt > 1 && !authctxt->info_req_seen) {
957                debug3("userauth_kbdint: disable: no info_req_seen");
958                dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL);
959                return 0;
960        }
961
962        debug2("userauth_kbdint");
963        packet_start(SSH2_MSG_USERAUTH_REQUEST);
964        packet_put_cstring(authctxt->server_user);
965        packet_put_cstring(authctxt->service);
966        packet_put_cstring(authctxt->method->name);
967        packet_put_cstring("");                                 /* lang */
968        packet_put_cstring(options.kbd_interactive_devices ?
969            options.kbd_interactive_devices : "");
970        packet_send();
971
972        dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
973        return 1;
974}
975
976/*
977 * parse INFO_REQUEST, prompt user and send INFO_RESPONSE
978 */
979void
980input_userauth_info_req(int type, int plen, void *ctxt)
981{
982        Authctxt *authctxt = ctxt;
983        char *name, *inst, *lang, *prompt, *response;
984        u_int num_prompts, i;
985        int echo = 0;
986
987        debug2("input_userauth_info_req");
988
989        if (authctxt == NULL)
990                fatal("input_userauth_info_req: no authentication context");
991
992        authctxt->info_req_seen = 1;
993
994        name = packet_get_string(NULL);
995        inst = packet_get_string(NULL);
996        lang = packet_get_string(NULL);
997        if (strlen(name) > 0)
998                log("%s", name);
999        if (strlen(inst) > 0)
1000                log("%s", inst);
1001        xfree(name);
1002        xfree(inst);
1003        xfree(lang);
1004
1005        num_prompts = packet_get_int();
1006        /*
1007         * Begin to build info response packet based on prompts requested.
1008         * We commit to providing the correct number of responses, so if
1009         * further on we run into a problem that prevents this, we have to
1010         * be sure and clean this up and send a correct error response.
1011         */
1012        packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE);
1013        packet_put_int(num_prompts);
1014
1015        debug2("input_userauth_info_req: num_prompts %d", num_prompts);
1016        for (i = 0; i < num_prompts; i++) {
1017                prompt = packet_get_string(NULL);
1018                echo = packet_get_char();
1019
1020                response = read_passphrase(prompt, echo ? RP_ECHO : 0);
1021
1022                packet_put_cstring(response);
1023                memset(response, 0, strlen(response));
1024                xfree(response);
1025                xfree(prompt);
1026        }
1027        packet_done(); /* done with parsing incoming message. */
1028
1029        packet_add_padding(64);
1030        packet_send();
1031}
1032
1033/*
1034 * this will be move to an external program (ssh-keysign) ASAP. ssh-keysign
1035 * will be setuid-root and the sbit can be removed from /usr/bin/ssh.
1036 */
1037int
1038userauth_hostbased(Authctxt *authctxt)
1039{
1040        Key *private = NULL;
1041        Buffer b;
1042        u_char *signature, *blob;
1043        char *chost, *pkalg, *p;
1044        const char *service;
1045        u_int blen, slen;
1046        int ok, i, len, found = 0;
1047
1048        /* check for a useful key */
1049        for (i = 0; i < authctxt->nkeys; i++) {
1050                private = authctxt->keys[i];
1051                if (private && private->type != KEY_RSA1) {
1052                        found = 1;
1053                        /* we take and free the key */
1054                        authctxt->keys[i] = NULL;
1055                        break;
1056                }
1057        }
1058        if (!found) {
1059                debug("userauth_hostbased: no more client hostkeys");
1060                return 0;
1061        }
1062        if (key_to_blob(private, &blob, &blen) == 0) {
1063                key_free(private);
1064                return 0;
1065        }
1066        /* figure out a name for the client host */
1067        p = get_local_name(packet_get_connection_in());
1068        if (p == NULL) {
1069                error("userauth_hostbased: cannot get local ipaddr/name");
1070                key_free(private);
1071                return 0;
1072        }
1073        len = strlen(p) + 2;
1074        chost = xmalloc(len);
1075        strlcpy(chost, p, len);
1076        strlcat(chost, ".", len);
1077        debug2("userauth_hostbased: chost %s", chost);
1078
1079        service = datafellows & SSH_BUG_HBSERVICE ? "ssh-userauth" :
1080            authctxt->service;
1081        pkalg = xstrdup(key_ssh_name(private));
1082        buffer_init(&b);
1083        /* construct data */
1084        buffer_put_string(&b, session_id2, session_id2_len);
1085        buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
1086        buffer_put_cstring(&b, authctxt->server_user);
1087        buffer_put_cstring(&b, service);
1088        buffer_put_cstring(&b, authctxt->method->name);
1089        buffer_put_cstring(&b, pkalg);
1090        buffer_put_string(&b, blob, blen);
1091        buffer_put_cstring(&b, chost);
1092        buffer_put_cstring(&b, authctxt->local_user);
1093#ifdef DEBUG_PK
1094        buffer_dump(&b);
1095#endif
1096        ok = key_sign(private, &signature, &slen, buffer_ptr(&b), buffer_len(&b));
1097        key_free(private);
1098        buffer_free(&b);
1099        if (ok != 0) {
1100                error("key_sign failed");
1101                xfree(chost);
1102                xfree(pkalg);
1103                return 0;
1104        }
1105        packet_start(SSH2_MSG_USERAUTH_REQUEST);
1106        packet_put_cstring(authctxt->server_user);
1107        packet_put_cstring(authctxt->service);
1108        packet_put_cstring(authctxt->method->name);
1109        packet_put_cstring(pkalg);
1110        packet_put_string(blob, blen);
1111        packet_put_cstring(chost);
1112        packet_put_cstring(authctxt->local_user);
1113        packet_put_string(signature, slen);
1114        memset(signature, 's', slen);
1115        xfree(signature);
1116        xfree(chost);
1117        xfree(pkalg);
1118
1119        packet_send();
1120        return 1;
1121}
1122
1123/* find auth method */
1124
1125/*
1126 * given auth method name, if configurable options permit this method fill
1127 * in auth_ident field and return true, otherwise return false.
1128 */
1129static int
1130authmethod_is_enabled(Authmethod *method)
1131{
1132        if (method == NULL)
1133                return 0;
1134        /* return false if options indicate this method is disabled */
1135        if  (method->enabled == NULL || *method->enabled == 0)
1136                return 0;
1137        /* return false if batch mode is enabled but method needs interactive mode */
1138        if  (method->batch_flag != NULL && *method->batch_flag != 0)
1139                return 0;
1140        return 1;
1141}
1142
1143static Authmethod *
1144authmethod_lookup(const char *name)
1145{
1146        Authmethod *method = NULL;
1147        if (name != NULL)
1148                for (method = authmethods; method->name != NULL; method++)
1149                        if (strcmp(name, method->name) == 0)
1150                                return method;
1151        debug2("Unrecognized authentication method name: %s", name ? name : "NULL");
1152        return NULL;
1153}
1154
1155/* XXX internal state */
1156static Authmethod *current = NULL;
1157static char *supported = NULL;
1158static char *preferred = NULL;
1159/*
1160 * Given the authentication method list sent by the server, return the
1161 * next method we should try.  If the server initially sends a nil list,
1162 * use a built-in default list.
1163 */
1164static Authmethod *
1165authmethod_get(char *authlist)
1166{
1167
1168        char *name = NULL;
1169        int next;
1170
1171        /* Use a suitable default if we're passed a nil list.  */
1172        if (authlist == NULL || strlen(authlist) == 0)
1173                authlist = options.preferred_authentications;
1174
1175        if (supported == NULL || strcmp(authlist, supported) != 0) {
1176                debug3("start over, passed a different list %s", authlist);
1177                if (supported != NULL)
1178                        xfree(supported);
1179                supported = xstrdup(authlist);
1180                preferred = options.preferred_authentications;
1181                debug3("preferred %s", preferred);
1182                current = NULL;
1183        } else if (current != NULL && authmethod_is_enabled(current))
1184                return current;
1185
1186        for (;;) {
1187                if ((name = match_list(preferred, supported, &next)) == NULL) {
1188                        debug("no more auth methods to try");
1189                        current = NULL;
1190                        return NULL;
1191                }
1192                preferred += next;
1193                debug3("authmethod_lookup %s", name);
1194                debug3("remaining preferred: %s", preferred);
1195                if ((current = authmethod_lookup(name)) != NULL &&
1196                    authmethod_is_enabled(current)) {
1197                        debug3("authmethod_is_enabled %s", name);
1198                        debug("next auth method to try is %s", name);
1199                        return current;
1200                }
1201        }
1202}
1203
1204
1205#define DELIM   ","
1206
1207static char *
1208authmethods_get(void)
1209{
1210        Authmethod *method = NULL;
1211        char buf[1024];
1212
1213        buf[0] = '\0';
1214        for (method = authmethods; method->name != NULL; method++) {
1215                if (authmethod_is_enabled(method)) {
1216                        if (buf[0] != '\0')
1217                                strlcat(buf, DELIM, sizeof buf);
1218                        strlcat(buf, method->name, sizeof buf);
1219                }
1220        }
1221        return xstrdup(buf);
1222}
Note: See TracBrowser for help on using the repository browser.