~ubuntu-branches/ubuntu/dapper/openssh/dapper

« back to all changes in this revision

Viewing changes to kexgsss.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2005-10-31 07:46:44 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20051031074644-poik7e4un4723tr4
Tags: 1:4.2p1-5ubuntu1
Resynchronise with Debian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2001-2004 Simon Wilkinson. 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"
 
26
 
 
27
#ifdef GSSAPI
 
28
 
 
29
#include <openssl/crypto.h>
 
30
#include <openssl/bn.h>
 
31
 
 
32
#include "xmalloc.h"
 
33
#include "buffer.h"
 
34
#include "bufaux.h"
 
35
#include "kex.h"
 
36
#include "log.h"
 
37
#include "packet.h"
 
38
#include "dh.h"
 
39
#include "ssh2.h"
 
40
#include "ssh-gss.h"
 
41
#include "monitor_wrap.h"
 
42
 
 
43
void
 
44
kexgss_server(Kex *kex)
 
45
{
 
46
        OM_uint32 maj_status, min_status;
 
47
        
 
48
        /* 
 
49
         * Some GSSAPI implementations use the input value of ret_flags (an
 
50
         * output variable) as a means of triggering mechanism specific 
 
51
         * features. Initializing it to zero avoids inadvertently 
 
52
         * activating this non-standard behaviour.
 
53
         */
 
54
 
 
55
        OM_uint32 ret_flags = 0;
 
56
        gss_buffer_desc gssbuf, send_tok, recv_tok, msg_tok;
 
57
        Gssctxt *ctxt = NULL;
 
58
        unsigned int klen, kout;
 
59
        unsigned char *kbuf, *hash;
 
60
        DH *dh;
 
61
        BIGNUM *shared_secret = NULL;
 
62
        BIGNUM *dh_client_pub = NULL;
 
63
        int type =0;
 
64
        u_int slen;
 
65
        gss_OID oid;
 
66
        
 
67
        /* Initialise GSSAPI */
 
68
 
 
69
        debug2("%s: Identifying %s", __func__, kex->name);
 
70
        oid = ssh_gssapi_id_kex(NULL, kex->name);
 
71
        if (oid == NULL)
 
72
           fatal("Unknown gssapi mechanism");
 
73
 
 
74
        debug2("%s: Acquiring credentials", __func__);
 
75
 
 
76
        if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
 
77
                fatal("Unable to acquire credentials for the server");
 
78
 
 
79
        do {
 
80
                debug("Wait SSH2_MSG_GSSAPI_INIT");
 
81
                type = packet_read();
 
82
                switch(type) {
 
83
                case SSH2_MSG_KEXGSS_INIT:
 
84
                        if (dh_client_pub != NULL) 
 
85
                                fatal("Received KEXGSS_INIT after initialising");
 
86
                        recv_tok.value = packet_get_string(&slen);
 
87
                        recv_tok.length = slen; 
 
88
 
 
89
                        dh_client_pub = BN_new();
 
90
 
 
91
                        if (dh_client_pub == NULL)
 
92
                                fatal("dh_client_pub == NULL");
 
93
                        packet_get_bignum2(dh_client_pub);
 
94
 
 
95
                        /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
 
96
                        break;
 
97
                case SSH2_MSG_KEXGSS_CONTINUE:
 
98
                        recv_tok.value = packet_get_string(&slen);
 
99
                        recv_tok.length = slen; 
 
100
                        break;
 
101
                default:
 
102
                        packet_disconnect(
 
103
                            "Protocol error: didn't expect packet type %d",
 
104
                            type);
 
105
                }
 
106
 
 
107
                maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 
 
108
                    &send_tok, &ret_flags));
 
109
 
 
110
                gss_release_buffer(&min_status, &recv_tok);
 
111
                
 
112
                if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
 
113
                        fatal("Zero length token output when incomplete");
 
114
 
 
115
                if (dh_client_pub == NULL)
 
116
                        fatal("No client public key");
 
117
                
 
118
                if (maj_status & GSS_S_CONTINUE_NEEDED) {
 
119
                        debug("Sending GSSAPI_CONTINUE");
 
120
                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
 
121
                        packet_put_string(send_tok.value, send_tok.length);
 
122
                        packet_send();
 
123
                        gss_release_buffer(&min_status, &send_tok);
 
124
                }
 
125
        } while (maj_status & GSS_S_CONTINUE_NEEDED);
 
126
 
 
127
        if (GSS_ERROR(maj_status)) {
 
128
                if (send_tok.length>0) {
 
129
                        packet_start(SSH2_MSG_KEXGSS_CONTINUE);
 
130
                        packet_put_string(send_tok.value, send_tok.length);
 
131
                        packet_send();
 
132
                }
 
133
                fatal("accept_ctx died");
 
134
        }
 
135
 
 
136
        if (!(ret_flags & GSS_C_MUTUAL_FLAG))
 
137
                fatal("Mutual Authentication flag wasn't set");
 
138
 
 
139
        if (!(ret_flags & GSS_C_INTEG_FLAG))
 
140
                fatal("Integrity flag wasn't set");
 
141
        
 
142
        dh = dh_new_group1();
 
143
        dh_gen_key(dh, kex->we_need * 8);
 
144
 
 
145
        if (!dh_pub_is_valid(dh, dh_client_pub))
 
146
                packet_disconnect("bad client public DH value");
 
147
 
 
148
        klen = DH_size(dh);
 
149
        kbuf = xmalloc(klen); 
 
150
        kout = DH_compute_key(kbuf, dh_client_pub, dh);
 
151
 
 
152
        shared_secret = BN_new();
 
153
        BN_bin2bn(kbuf, kout, shared_secret);
 
154
        memset(kbuf, 0, klen);
 
155
        xfree(kbuf);
 
156
 
 
157
        /* The GSSAPI hash is identical to the Diffie Helman one */
 
158
        hash = kex_dh_hash(
 
159
            kex->client_version_string, kex->server_version_string,
 
160
            buffer_ptr(&kex->peer), buffer_len(&kex->peer),
 
161
            buffer_ptr(&kex->my), buffer_len(&kex->my),
 
162
            NULL, 0, /* Change this if we start sending host keys */
 
163
            dh_client_pub, dh->pub_key, shared_secret
 
164
        );
 
165
        BN_free(dh_client_pub);
 
166
 
 
167
        if (kex->session_id == NULL) {
 
168
                kex->session_id_len = 20;
 
169
                kex->session_id = xmalloc(kex->session_id_len);
 
170
                memcpy(kex->session_id, hash, kex->session_id_len);
 
171
        }
 
172
 
 
173
        gssbuf.value = hash;
 
174
        gssbuf.length = 20; /* Hashlen appears to always be 20 */
 
175
 
 
176
        if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok))))
 
177
                fatal("Couldn't get MIC");
 
178
 
 
179
        packet_start(SSH2_MSG_KEXGSS_COMPLETE);
 
180
        packet_put_bignum2(dh->pub_key);
 
181
        packet_put_string((char *)msg_tok.value,msg_tok.length);
 
182
 
 
183
        if (send_tok.length!=0) {
 
184
                packet_put_char(1); /* true */
 
185
                packet_put_string((char *)send_tok.value, send_tok.length);
 
186
        } else {
 
187
                packet_put_char(0); /* false */
 
188
        }
 
189
        packet_send();
 
190
 
 
191
        gss_release_buffer(&min_status, &send_tok);     
 
192
 
 
193
        if (gss_kex_context == NULL)
 
194
                gss_kex_context = ctxt;
 
195
        else 
 
196
                ssh_gssapi_delete_ctx(&ctxt);
 
197
 
 
198
        DH_free(dh);
 
199
 
 
200
        kex_derive_keys(kex, hash, shared_secret);
 
201
        BN_clear_free(shared_secret);
 
202
        kex_finish(kex);
 
203
}
 
204
#endif /* GSSAPI */