~ubuntu-branches/debian/lenny/dropbear/lenny

« back to all changes in this revision

Viewing changes to algo.c

  • Committer: Bazaar Package Importer
  • Author(s): Gerrit Pape
  • Date: 2005-05-25 22:38:17 UTC
  • mfrom: (1.2.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050525223817-fdl653extybmz1zb
Tags: 0.45-3
* debian/dropbear.init: init script prints human readable message in case
  it's disabled (closes: #309099).
* debian/dropbear.postinst: configure: restart service through init script
  instead of start.
* debian/dropbear.prerm: set -u -> set -e.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Dropbear - a SSH2 server
3
 
 * 
4
 
 * Copyright (c) 2002,2003 Matt Johnston
5
 
 * All rights reserved.
6
 
 * 
7
 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 
 * of this software and associated documentation files (the "Software"), to deal
9
 
 * in the Software without restriction, including without limitation the rights
10
 
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 
 * copies of the Software, and to permit persons to whom the Software is
12
 
 * furnished to do so, subject to the following conditions:
13
 
 * 
14
 
 * The above copyright notice and this permission notice shall be included in
15
 
 * all copies or substantial portions of the Software.
16
 
 * 
17
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23
 
 * SOFTWARE. */
24
 
 
25
 
#include "algo.h"
26
 
#include "dbutil.h"
27
 
 
28
 
/* This file (algo.c) organises the ciphers which can be used, and is used to
29
 
 * decide which ciphers/hashes/compression/signing to use during key exchange*/
30
 
 
31
 
/* Mappings for ciphers, parameters are
32
 
   {&cipher_desc, keysize, blocksize} */
33
 
 
34
 
#ifdef DROPBEAR_AES128_CBC
35
 
const struct dropbear_cipher dropbear_aes128 = 
36
 
        {&rijndael_desc, 16, 16};
37
 
#endif
38
 
#ifdef DROPBEAR_BLOWFISH_CBC
39
 
const struct dropbear_cipher dropbear_blowfish = 
40
 
        {&blowfish_desc, 16, 8};
41
 
#endif
42
 
#ifdef DROPBEAR_TWOFISH128_CBC
43
 
const struct dropbear_cipher dropbear_twofish128 = 
44
 
        {&twofish_desc, 16, 16};
45
 
#endif
46
 
#ifdef DROPBEAR_3DES_CBC
47
 
const struct dropbear_cipher dropbear_3des = 
48
 
        {&des3_desc, 24, 8};
49
 
#endif
50
 
 
51
 
/* used to indicate no encryption, as defined in rfc2410 */
52
 
const struct dropbear_cipher dropbear_nocipher =
53
 
        {NULL, 16, 8}; 
54
 
 
55
 
/* Mapping of ssh hashes to libtomcrypt hashes, including keysize etc.
56
 
   {&hash_desc, keysize, hashsize} */
57
 
 
58
 
#ifdef DROPBEAR_SHA1_HMAC
59
 
const struct dropbear_hash dropbear_sha1 = 
60
 
        {&sha1_desc, 20, 20};
61
 
#endif
62
 
#ifdef DROPBEAR_MD5_HMAC
63
 
const struct dropbear_hash dropbear_md5 = 
64
 
        {&md5_desc, 16, 16};
65
 
#endif
66
 
 
67
 
const struct dropbear_hash dropbear_nohash =
68
 
        {NULL, 16, 0}; /* used initially */
69
 
        
70
 
 
71
 
/* The following map ssh names to internal values */
72
 
 
73
 
algo_type sshciphers[] = {
74
 
#ifdef DROPBEAR_AES128_CBC
75
 
        {"aes128-cbc", 0, (void*)&dropbear_aes128, 1},
76
 
#endif
77
 
#ifdef DROPBEAR_BLOWFISH_CBC
78
 
        {"blowfish-cbc", 0, (void*)&dropbear_blowfish, 1},
79
 
#endif
80
 
#ifdef DROPBEAR_TWOFISH128_CBC
81
 
        {"twofish-cbc", 0, (void*)&dropbear_twofish128, 1},
82
 
#endif
83
 
#ifdef DROPBEAR_3DES_CBC
84
 
        {"3des-cbc", 0, (void*)&dropbear_3des, 1},
85
 
#endif
86
 
        {NULL, 0, NULL, 0}
87
 
};
88
 
 
89
 
algo_type sshhashes[] = {
90
 
#ifdef DROPBEAR_SHA1_HMAC
91
 
        {"hmac-sha1", 0, (void*)&dropbear_sha1, 1},
92
 
#endif
93
 
#ifdef DROPBEAR_MD5_HMAC
94
 
        {"hmac-md5", 0, (void*)&dropbear_md5, 1},
95
 
#endif
96
 
        {NULL, 0, NULL, 0}
97
 
};
98
 
 
99
 
algo_type sshcompress[] = {
100
 
        {"none", DROPBEAR_COMP_NONE, NULL, 1},
101
 
#ifndef DISABLE_ZLIB
102
 
        {"zlib", DROPBEAR_COMP_ZLIB, NULL, 1},
103
 
#endif
104
 
        {NULL, 0, NULL, 0}
105
 
};
106
 
 
107
 
algo_type sshhostkey[] = {
108
 
#ifdef DROPBEAR_RSA
109
 
        {"ssh-rsa", DROPBEAR_SIGNKEY_RSA, NULL, 1},
110
 
#endif
111
 
#ifdef DROPBEAR_DSS
112
 
        {"ssh-dss", DROPBEAR_SIGNKEY_DSS, NULL, 1},
113
 
#endif
114
 
        {NULL, 0, NULL, 0}
115
 
};
116
 
 
117
 
algo_type sshkex[] = {
118
 
        {"diffie-hellman-group1-sha1", DROPBEAR_KEX_DH_GROUP1, NULL, 1},
119
 
        {NULL, 0, NULL, 0}
120
 
};
121
 
 
122
 
 
123
 
/* Register the compiled in ciphers.
124
 
 * This should be run before using any of the ciphers/hashes */
125
 
void crypto_init() {
126
 
 
127
 
        const struct _cipher_descriptor *regciphers[] = {
128
 
#ifdef DROPBEAR_AES128_CBC
129
 
                &rijndael_desc,
130
 
#endif
131
 
#ifdef DROPBEAR_BLOWFISH_CBC
132
 
                &blowfish_desc,
133
 
#endif
134
 
#ifdef DROPBEAR_TWOFISH128_CBC
135
 
                &twofish_desc,
136
 
#endif
137
 
#ifdef DROPBEAR_3DES_CBC
138
 
                &des3_desc,
139
 
#endif
140
 
                NULL
141
 
        };
142
 
 
143
 
        const struct _hash_descriptor *reghashes[] = {
144
 
                /* we need sha1 for hostkey stuff regardless */
145
 
                &sha1_desc,
146
 
#ifdef DROPBEAR_MD5_HMAC
147
 
                &md5_desc,
148
 
#endif
149
 
                NULL
150
 
        };      
151
 
        int i;
152
 
        
153
 
        for (i = 0; regciphers[i] != NULL; i++) {
154
 
                if (register_cipher(regciphers[i]) == -1) {
155
 
                        dropbear_exit("error registering crypto");
156
 
                }
157
 
        }
158
 
 
159
 
        for (i = 0; reghashes[i] != NULL; i++) {
160
 
                if (register_hash(reghashes[i]) == -1) {
161
 
                        dropbear_exit("error registering crypto");
162
 
                }
163
 
        }
164
 
}
165
 
 
166
 
/* algolen specifies the length of algo, algos is our local list to match
167
 
 * against.
168
 
 * Returns DROPBEAR_SUCCESS if we have a match for algo, DROPBEAR_FAILURE
169
 
 * otherwise */
170
 
int have_algo(char* algo, size_t algolen, algo_type algos[]) {
171
 
 
172
 
        int i;
173
 
 
174
 
        for (i = 0; algos[i].name != NULL; i++) {
175
 
                if (strlen(algos[i].name) == algolen
176
 
                                && (strncmp(algos[i].name, algo, algolen) == 0)) {
177
 
                        return DROPBEAR_SUCCESS;
178
 
                }
179
 
        }
180
 
 
181
 
        return DROPBEAR_FAILURE;
182
 
}
183
 
 
184
 
 
185
 
/* match the first algorithm in the comma-separated list in buf which is
186
 
 * also in localalgos[], or return NULL on failure.
187
 
 * (*goodguess) is set to 1 if the preferred client/server algos match,
188
 
 * 0 otherwise. This is used for checking if the kexalgo/hostkeyalgos are
189
 
 * guessed correctly */
190
 
algo_type * buf_match_algo(buffer* buf, algo_type localalgos[], int *goodguess)
191
 
{
192
 
 
193
 
        unsigned char * algolist = NULL;
194
 
        unsigned char * remotealgos[MAX_PROPOSED_ALGO];
195
 
        unsigned int len;
196
 
        unsigned int count, i, j;
197
 
        algo_type * ret = NULL;
198
 
 
199
 
        /* get the comma-separated list from the buffer ie "algo1,algo2,algo3" */
200
 
        algolist = buf_getstring(buf, &len);
201
 
        /* Debug this */
202
 
        TRACE(("buf_match_algo: %s", algolist));
203
 
        if (len > MAX_PROPOSED_ALGO*(MAX_NAME_LEN+1)) {
204
 
                goto out; /* just a sanity check, no other use */
205
 
        }
206
 
 
207
 
        /* remotealgos will contain a list of the strings parsed out */
208
 
        /* We will have at least one string (even if it's just "") */
209
 
        remotealgos[0] = algolist;
210
 
        count = 1;
211
 
        /* Iterate through, replacing ','s with NULs, to split it into
212
 
         * words. */
213
 
        for (i = 0; i < len; i++) {
214
 
                if (algolist[i] == '\0') {
215
 
                        /* someone is trying something strange */
216
 
                        goto out;
217
 
                }
218
 
                if (algolist[i] == ',') {
219
 
                        algolist[i] = '\0';
220
 
                        remotealgos[count] = &algolist[i+1];
221
 
                        count++;
222
 
                }
223
 
                if (count == MAX_PROPOSED_ALGO) {
224
 
                        break;
225
 
                }
226
 
        }
227
 
 
228
 
        /* iterate and find the first match */
229
 
        for (i = 0; i < count; i++) {
230
 
 
231
 
                len = strlen(remotealgos[i]);
232
 
 
233
 
                for (j = 0; localalgos[j].name != NULL; j++) {
234
 
                        if (localalgos[j].usable) {
235
 
                                if (len == strlen(localalgos[j].name) &&
236
 
                                                strncmp(localalgos[j].name, remotealgos[i], len) == 0) {
237
 
                                        /* set if it was a good guess */
238
 
                                        if (i == 0 && j == 0) {
239
 
                                                *goodguess = 1;
240
 
                                        } else {
241
 
                                                *goodguess = 0;
242
 
                                        }
243
 
                                        /* set the algo to return */
244
 
                                        ret = &localalgos[j];
245
 
                                        goto out;
246
 
                                }
247
 
                        }
248
 
                }
249
 
        }
250
 
 
251
 
out:
252
 
        m_free(algolist);
253
 
        return ret;
254
 
}
255
 
 
256
 
/* Output a comma separated list of algorithms to a buffer */
257
 
void buf_put_algolist(buffer * buf, algo_type localalgos[]) {
258
 
 
259
 
        unsigned int pos = 0, i, len;
260
 
        char str[50]; /* enough for local algo storage */
261
 
 
262
 
        for (i = 0; localalgos[i].name != NULL; i++) {
263
 
                if (localalgos[i].usable) {
264
 
                        /* Avoid generating a trailing comma */
265
 
                        if (pos)
266
 
                            str[pos++] = ',';
267
 
                        len = strlen(localalgos[i].name);
268
 
                        memcpy(&str[pos], localalgos[i].name, len);
269
 
                        pos += len;
270
 
                }
271
 
        }
272
 
        str[pos]=0;
273
 
        /* Debug this */
274
 
        TRACE(("buf_put_algolist: %s", str));
275
 
        buf_putstring(buf, str, pos);
276
 
}