summaryrefslogtreecommitdiff
path: root/other/guess-who/ssh.cc
diff options
context:
space:
mode:
authorSkyperTHC2026-03-03 06:28:55 +0000
committerSkyperTHC2026-03-03 06:28:55 +0000
commit5d3573ef7a109ee70416fe94db098fe6a769a798 (patch)
treedc2d5b294c9db8ab2db7433511f94e1c4bb8b698 /other/guess-who/ssh.cc
parentc6c59dc73cc4586357f93ab38ecf459e98675cc5 (diff)
packetstorm sync
Diffstat (limited to 'other/guess-who/ssh.cc')
-rw-r--r--other/guess-who/ssh.cc677
1 files changed, 677 insertions, 0 deletions
diff --git a/other/guess-who/ssh.cc b/other/guess-who/ssh.cc
new file mode 100644
index 0000000..11055da
--- /dev/null
+++ b/other/guess-who/ssh.cc
@@ -0,0 +1,677 @@
1/*
2 * Copyright (C) 2002,2003 Sebastian Krahmer.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Sebastian Krahmer.
16 * 4. The name Sebastian Krahmer may not be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
21 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32#include <stdio.h>
33#include <sys/types.h>
34#include <errno.h>
35#include <string.h>
36#include <unistd.h>
37#include <assert.h>
38#include <netinet/in.h>
39#include <sys/stat.h>
40
41extern "C" {
42#include <openssl/dh.h>
43#include <openssl/bn.h>
44#include <openssl/hmac.h>
45#include <openssl/evp.h>
46#include <openssl/rsa.h>
47};
48
49#include <pthread.h>
50
51#include "ssh.h"
52#include "misc.h"
53#include "base64.h"
54
55using namespace std;
56
57DH *dh_new_group_asc(const char *gen, const char *modulus)
58{
59 DH *dh;
60
61 dh = DH_new();
62 if (dh == NULL)
63 fprintf(stderr, "DH_new returned NULL");
64
65 if (BN_hex2bn(&dh->p, modulus) == 0)
66 fprintf(stderr, "BN_hex2bn (p) returned 0");
67 if (BN_hex2bn(&dh->g, gen) == 0)
68 fprintf(stderr, "BN_hex2bn (g) returned 0");
69
70 return (dh);
71}
72
73/*
74 * This just returns the group, we still need to generate the exchange
75 * value.
76 */
77
78DH *dh_new_group(BIGNUM *gen, BIGNUM *modulus)
79{
80 DH *dh;
81
82 dh = DH_new();
83 if (dh == NULL)
84 fprintf(stderr, "DH_new returned NULL");
85 dh->p = modulus;
86 dh->g = gen;
87
88 return (dh);
89}
90
91DH *dh_new_group1(void)
92{
93 static char *gen = "2", *group1 =
94 "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
95 "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
96 "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
97 "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
98 "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
99 "FFFFFFFF" "FFFFFFFF";
100
101 return (dh_new_group_asc(gen, group1));
102}
103
104
105int SSH2::packet_write(const void *buf, size_t buflen)
106{
107 unsigned char packet[32768], pad[16],
108 padding, mac[20];
109 unsigned char *ptr = packet, *enc_packet = NULL;
110 unsigned short paylen = 0;
111 size_t mac_len = sizeof(mac);
112 int r;
113
114 assert(buflen < 32000);
115
116 padding = 8 - ((buflen+1+4) % 8);
117 if (padding < 4)
118 padding += 8;
119 *(u_int32_t*)ptr = htonl(buflen+1+padding); // paylen
120 ptr += sizeof(u_int32_t);
121 paylen += sizeof(u_int32_t);
122 *ptr = padding;
123 ++ptr;
124 ++paylen;
125 memcpy(ptr, buf, buflen);
126 ptr += buflen;
127 paylen += buflen;
128 memcpy(ptr, pad, padding);
129 paylen += padding;
130 ptr += paylen;
131
132 if (use_crypto) {
133 HMAC_CTX c;
134 u_int32_t s = htonl(seq);
135 HMAC_Init(&c, s_mac, sizeof(s_mac), EVP_sha1());
136 HMAC_Update(&c, (unsigned char*)&s, sizeof(s));
137 HMAC_Update(&c, packet, paylen);
138 HMAC_Final(&c, mac, &mac_len);
139 }
140
141 ++seq; // one more packet written
142 if (debug > 0)
143 fprintf(stderr, "sending %d byte (%d padding) ", paylen, padding);
144
145 if (use_crypto) {
146 if (debug > 0)
147 fprintf(stderr, "crypted\n");
148 enc_packet = new unsigned char[paylen+mac_len];
149 des_ede3_cbc_encrypt(packet, enc_packet, paylen,
150 s_key1, s_key2, s_key3,
151 &s_iv, DES_ENCRYPT);
152 memcpy(enc_packet+paylen, mac, mac_len);
153 r = writen(peer, enc_packet, paylen+mac_len);
154 delete [] enc_packet;
155 } else {
156 if (debug > 0)
157 fprintf(stderr, "plain\n");
158 r = writen(peer, packet, paylen);
159 if (r <= 0) {
160 error = "SSH2::packet_write::write(): ";
161 error += strerror(errno);
162 }
163 }
164 return r;
165}
166
167
168// return the number bytes read or -1 on error
169// puts length of payload in n. packet may be trunced if
170// plen < 32768
171int SSH2::packet_read(unsigned char *plain_buf, size_t pblen, size_t *n)
172{
173 unsigned char buf[32768], *ptr = NULL;
174 unsigned char dec_packet[32768];
175
176 int r;
177
178 if ((r = read(peer, buf, sizeof(buf))) <= 0) {
179 error = "SSH2::packet_read::read() ";
180 error += strerror(errno);
181 return -1;
182 }
183
184 // maybe TODO: check MAC
185 if (use_crypto) {
186 if (r - 20 < 0) {
187 error = "SSH2::read_packet: Invalid packet ";
188 return -1;
189 }
190 des_ede3_cbc_encrypt(buf, dec_packet, r-20,
191 r_key1, r_key2, r_key3,
192 &r_iv, DES_DECRYPT);
193 ptr = dec_packet;
194 } else
195 ptr = buf;
196
197 *n = ntohl(*(u_int32_t*)ptr);
198 ptr += sizeof(u_int32_t);
199 *n -= *ptr; // minus paylen
200 --*n; // minus one
201 if (*n > (size_t)r) {
202 error = "SSH2::packet_read: bad packet size";
203 return -1;
204 }
205
206 ++ptr;
207 memcpy(plain_buf, ptr, pblen < *n ? pblen : *n);
208 return r;
209}
210
211
212int SSH2::banner_exchange()
213{
214 int r;
215 char buf[1024], banner[] = "SSH-2.0-guess-who\r\n";
216
217 // Add V_C to hash input
218 to_hash_len = strlen(banner)-2 + sizeof(u_int32_t);
219 to_hash = (unsigned char*)realloc(to_hash, to_hash_len);
220 *(u_int32_t*)to_hash = htonl(strlen(banner)-2);
221 memcpy(&to_hash[sizeof(u_int32_t)], banner, strlen(banner)-2);
222
223 memset(buf, 0, sizeof(buf));
224 if ((r = read(peer, buf, sizeof(buf))) <= 0) {
225 error = "SSH2::banner_exchange::read() ";
226 error += strerror(errno);
227 return -1;
228 }
229 char *crlf;
230 if ((crlf = strchr(buf, '\n')) != NULL)
231 *crlf = 0;
232 if ((crlf = strchr(buf, '\r')) != NULL)
233 *crlf = 0;
234 snprintf(d_banner, sizeof(buf), "%s", buf);
235
236 // Add V_S to hash input
237 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+strlen(buf) + sizeof(u_int32_t));
238 *(u_int32_t*)&to_hash[to_hash_len] = htonl(strlen(buf));
239 to_hash_len += sizeof(u_int32_t);
240 memcpy(&to_hash[to_hash_len], buf, strlen(buf));
241 to_hash_len += strlen(buf);
242
243 if ((r = writen(peer, banner, strlen(banner))) <= 0) {
244 error = "SSH2::banner_exchange::writen() ";
245 error = strerror(errno);
246 }
247
248 return 0;
249}
250
251
252int SSH2::kex_init()
253{
254 char my_kex_msg[] =
255 "\x14" // SSH_MSG_KEXINIT
256 "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
257 "\x00\x00\x00\x1a" "diffie-hellman-group1-sha1" // kex algo
258 "\x00\x00\x00\x07" "ssh-dss" // server hostkey algo
259 "\x00\x00\x00\x08" "3des-cbc" // client to server enc algo
260 "\x00\x00\x00\x08" "3des-cbc" // server to client enc algo
261 "\x00\x00\x00\x09" "hmac-sha1" // client to server MAC algo
262 "\x00\x00\x00\x09" "hmac-sha1" // server to client MAC algo
263 "\x00\x00\x00\x04" "none" // client to server comp algo
264 "\x00\x00\x00\x04" "none" // server to client comp algo
265 "\x00\x00\x00\x00" // client to server language
266 "\x00\x00\x00\x00" // server to client language
267 "\x00"
268 "\x00\x00\x00\x00";
269 unsigned char buf[1024], *ptr;
270 int r;
271 size_t n;
272
273 // Add I_C to hash input
274 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+sizeof(my_kex_msg)-1+sizeof(u_int32_t));
275 *(u_int32_t*)&to_hash[to_hash_len] = htonl(sizeof(my_kex_msg)-1);
276 to_hash_len += sizeof(u_int32_t);
277 memcpy(&to_hash[to_hash_len], my_kex_msg, sizeof(my_kex_msg)-1);
278 to_hash_len += sizeof(my_kex_msg)-1;
279
280 r = packet_write(my_kex_msg, sizeof(my_kex_msg)-1);
281 if (r < 0) {
282 error = "SSH2::kex_init::packet_write() ";
283 error = strerror(errno);
284 return -1;
285 }
286 if (packet_read(buf, sizeof(buf), &n) <= 0)
287 return -1;
288 ptr = buf;
289 if (*ptr != SSH_MSG_KEXINIT) {
290 error = "SSH2::kex_init: packet type != SSH_MSG_KEXINIT";
291 return -1;
292 }
293
294 // Add I_S to hash input
295 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+n+sizeof(u_int32_t));
296 *(u_int32_t*)&to_hash[to_hash_len] = htonl(n);
297 to_hash_len += sizeof(u_int32_t);
298 memcpy(&to_hash[to_hash_len], ptr, n);
299 to_hash_len += n;
300
301 return 0;
302}
303
304
305int SSH2::hash_helper(const char *letter, unsigned char d1[20],
306 unsigned char d2[20], bool expand)
307{
308 EVP_MD_CTX md;
309 EVP_DigestInit(&md, EVP_sha1());
310
311 // shared_secret as mpint
312 unsigned char *secret = new unsigned char[shared_secret_len+1+4];
313 int h = *shared_secret & 0x80 ? 1 : 0;
314 *(u_int32_t*)secret = htonl(shared_secret_len+h);
315 secret[sizeof(u_int32_t)] = 0;
316 memcpy(&secret[sizeof(u_int32_t)+h], shared_secret, shared_secret_len);
317
318 EVP_DigestUpdate(&md, secret, shared_secret_len+h+4);
319 EVP_DigestUpdate(&md, session_id, sizeof(session_id));
320 EVP_DigestUpdate(&md, (unsigned char*)letter, 1);
321 EVP_DigestUpdate(&md, session_id, sizeof(session_id));
322 EVP_DigestFinal(&md, d1, NULL);
323
324 // Our expansion gives 40bytes, enough for 3DES keys and IV's
325 if (expand) {
326 EVP_DigestInit(&md, EVP_sha1());
327 EVP_DigestUpdate(&md, secret, shared_secret_len+h+4);
328 EVP_DigestUpdate(&md, session_id, sizeof(session_id));
329 EVP_DigestUpdate(&md, d1, 20); // sizeof(d1) == 4 !!!
330 EVP_DigestFinal(&md, d2, NULL);
331 }
332
333 delete [] secret;
334 return 0;
335}
336
337
338int SSH2::derive_keys()
339{
340 // First, compute HASH == session_id
341 EVP_MD_CTX md;
342 EVP_DigestInit(&md, EVP_sha1());
343 EVP_DigestUpdate(&md, to_hash, to_hash_len);
344 EVP_DigestFinal(&md, session_id, NULL);
345
346 if (debug > 1)
347 buffer_dump("session_id", session_id, sizeof(session_id));
348
349 unsigned char d1[20], d2[20];
350 hash_helper("A", d1, d2, 0); memcpy(s_iv, d1, 8);
351 hash_helper("B", d1, d2, 0); memcpy(r_iv, d1, 8);
352
353 // Now for the encryption keys: we need to expand to 24 byte
354 hash_helper("C", d1, d2, 1);
355 des_set_key((const_des_cblock*)d1, s_key1);
356 des_set_key((const_des_cblock*)(d1+8), s_key2);
357
358 // last 4 byte of d1 and first 4 byte of d2 build 3rd key. ufff.
359 unsigned char dummy[8];
360 memcpy(dummy, d1+16, 4); memcpy(dummy+4, d2, 4);
361 des_set_key((const_des_cblock*)dummy, s_key3);
362// buffer_dump("C", d1, 20);
363// buffer_dump("C", d2, 4);
364
365
366 hash_helper("D", d1, d2, 1);
367// buffer_dump("D", d1, 20);
368// buffer_dump("D", d2, 4);
369
370
371 des_set_key((const_des_cblock*)d1, r_key1);
372 des_set_key((const_des_cblock*)(d1+8), r_key2);
373 memcpy(dummy, d1+16, 4); memcpy(dummy+4, d2, 4);
374 des_set_key((const_des_cblock*)dummy, r_key3);
375
376 // MAC keys have same length as their hashoutput of used
377 // hashing function
378 hash_helper("E", s_mac, d2, 0);
379 hash_helper("F", r_mac, d2, 0);
380 return 0;
381}
382
383
384
385int SSH2::dh_exchange()
386{
387 DH *e = dh_new_group1();
388
389 // generate x as in secsh-draft
390 e->priv_key = BN_new();
391 if (BN_rand(e->priv_key, 1024, 0, 0) == 0) {
392 error = "SSH2::dh_exchange::BN_rand() returned 0";
393 return -1;
394 }
395 // compute e = g^x mod p
396 if (DH_generate_key(e) == 0) {
397 error = "SSH2::dh_exchange::DH_generate_key() returned 0";
398 return -1;
399 }
400 unsigned char *e_bin = new unsigned char[BN_num_bytes(e->pub_key)+1+1+4];
401 unsigned char *e_tmp = new unsigned char[BN_num_bytes(e->pub_key)];
402
403 assert(e_bin && e_tmp);
404
405 BN_bn2bin(e->pub_key, e_tmp);
406 int h = *e_tmp & 0x80 ? 1 : 0;
407
408 // send e as mpint across network
409 e_bin[0] = SSH_MSG_KEXDH_INIT;
410
411 // Somehow OpenSSH looks whether e is signed and adds 0x00 in front
412 // if so (length incremented by one). 'h' is true when highbit is set
413 // Thats why we mess with e_tmp: We need to add 0x00 in some cases and
414 // stretch the length by one. Same for shared_secret few lines later.
415 e_bin[5] = 0;
416 *(u_int32_t*)&e_bin[1] = htonl(BN_num_bytes(e->pub_key)+h);
417 memcpy(&e_bin[5+h], e_tmp, BN_num_bytes(e->pub_key));
418 packet_write(e_bin, BN_num_bytes(e->pub_key)+h+1+4);
419
420 delete [] e_tmp;
421
422
423 size_t n;
424 unsigned char server_blob[32768], *ptr = server_blob;
425 if (packet_read(server_blob, sizeof(server_blob), &n) <= 0)
426 return -1;
427
428 if (*ptr != SSH_MSG_KEXDH_REPLY) {
429 error = "SSH2::dh_exchange: type != SSH_MSG_KEXDH_REPLY";
430 return -1;
431 }
432 ++ptr;
433
434 // hostkey is a string
435 size_t hostkey_len = ntohl(*(u_int32_t*)ptr);
436
437
438 // Add K_S to hash input, its already in string format
439 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+hostkey_len+sizeof(u_int32_t));
440 memcpy(&to_hash[to_hash_len], ptr, hostkey_len+sizeof(u_int32_t));
441 to_hash_len += hostkey_len + sizeof(u_int32_t);
442
443 ptr += sizeof(u_int32_t);
444 ptr += hostkey_len;
445
446 // Add e to hash input, already in mpint format at &e_bin[1]
447 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+BN_num_bytes(e->pub_key)+h+4);
448 memcpy(&to_hash[to_hash_len], e_bin+1, BN_num_bytes(e->pub_key)+h+4);
449 to_hash_len += BN_num_bytes(e->pub_key)+h+4;
450
451 delete [] e_bin;
452
453 if (debug > 0)
454 fprintf(stderr, "hostkey_len=%d\n", hostkey_len);
455
456 // get f. f is mpint (which is same as string :)
457 size_t f_len = ntohl(*(u_int32_t*)ptr);
458
459
460 // Add f to hash input, already in mpint format
461 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+f_len+sizeof(u_int32_t));
462 memcpy(&to_hash[to_hash_len], ptr, f_len+sizeof(u_int32_t));
463 to_hash_len += f_len+sizeof(u_int32_t);
464
465 // go to f
466 ptr += sizeof(u_int32_t);
467
468 BIGNUM *f = BN_new();
469 BN_bin2bn(ptr, f_len, f);
470
471 shared_secret = new unsigned char[DH_size(e)];
472 shared_secret_len = DH_compute_key(shared_secret, f, e);
473
474 // Add shared_secret to hash input
475 // Once again, add 0x00 of it is signed
476 h = *shared_secret & 0x80 ? 1 : 0;
477 to_hash = (unsigned char*)realloc(to_hash, to_hash_len+shared_secret_len+sizeof(u_int32_t)+h);
478 *(u_int32_t*)&to_hash[to_hash_len] = htonl(shared_secret_len+h);
479 to_hash_len += sizeof(u_int32_t);
480 to_hash[to_hash_len] = 0;
481 memcpy(&to_hash[to_hash_len+h], shared_secret, shared_secret_len);
482 to_hash_len += shared_secret_len+h;
483
484
485 if (debug > 1)
486 buffer_dump("shared_secret", shared_secret, shared_secret_len);
487// buffer_dump("to_hash", to_hash, to_hash_len);
488
489 derive_keys();
490
491 return 0;
492}
493
494
495int SSH2::newkeys()
496{
497 char c = SSH_MSG_NEWKEYS;
498 int r = packet_write(&c, 1);
499 use_crypto = 1;
500 return r;
501}
502
503
504int SSH2::userauth_passwd(const char *user, const char *password)
505{
506 char preq[32768], *ptr = preq;
507 size_t preq_len = 0, l, n;
508 unsigned char reply[32768];
509
510 assert(strlen(user) + strlen(password) < 32000);
511
512
513 preq[0] = SSH_MSG_SERVICE_REQUEST;
514 ++ptr;
515 *(u_int32_t*)ptr = htonl(12);
516 ptr += sizeof(u_int32_t);
517 memcpy(ptr, "ssh-userauth", 12);
518 ptr += 12;
519 packet_write(preq, ptr-preq);
520 if (packet_read(reply, sizeof(reply), &n) < 0)
521 return -1;
522 if (reply[0] != SSH_MSG_SERVICE_ACCEPT) {
523 error = "SSH2::userauth_passwd: 'ssh-userauth' message not accepted";
524 sprintf(preq, "(%d)", reply[0]);
525 error += preq;
526 return -1;
527 }
528 ptr = preq;
529 preq[0] = SSH_MSG_USERAUTH_REQUEST;
530 ++ptr;
531 ++preq_len;
532
533 *(u_int32_t*)ptr = htonl(strlen(user));
534 ptr += sizeof(u_int32_t);
535 preq_len += sizeof(u_int32_t);
536 memcpy(ptr, user, strlen(user));
537 ptr += strlen(user);
538 preq_len += strlen(user);
539
540 *(u_int32_t*)ptr = htonl((l = strlen("ssh-connection")));
541 ptr += sizeof(u_int32_t);
542 preq_len += sizeof(u_int32_t);
543 memcpy(ptr, "ssh-connection", l);
544 ptr += l;
545 preq_len += l;
546
547 *(u_int32_t*)ptr = htonl((l = strlen("password")));
548 ptr += sizeof(u_int32_t);
549 preq_len += sizeof(u_int32_t);
550 memcpy(ptr, "password", l);
551 ptr += l;
552 preq_len += l;
553
554 *ptr = 0; // FALSE ;-)
555 ++ptr;
556 ++preq_len;
557
558 *(u_int32_t*)ptr = htonl((l = strlen(password)));
559 ptr += sizeof(u_int32_t);
560 preq_len += sizeof(u_int32_t);
561 memcpy(ptr, password, l);
562 ptr += l;
563 preq_len += l;
564
565 packet_write(preq, preq_len);
566
567 memset(reply, 0, sizeof(reply));
568 do {
569 if (packet_read(reply, sizeof(reply), &n) < 0)
570 return -1;
571 } while (reply[0] != SSH_MSG_USERAUTH_FAILURE &&
572 reply[0] != SSH_MSG_USERAUTH_SUCCESS);
573
574 return (reply[0] == SSH_MSG_USERAUTH_FAILURE);
575}
576
577/* Only checks whether pubkey is valid */
578int SSH2::userauth_pubkey(const char *user, const char *keyfile)
579{
580 struct stat st;
581 unsigned char reply[1024];
582 size_t n, l;
583
584 FILE *f = fopen(keyfile, "r");
585 if (!f || stat(keyfile, &st) < 0) {
586 error = "SSH2::userauth_pubkey: ";
587 error += strerror(errno);
588 return -1;
589 }
590 char *buf = new char[st.st_size];
591 fgets(buf, st.st_size, f);
592
593 // jump over ssh-rsa
594 char *keyblob64 = strstr(buf, "ssh-rsa ");
595 if (!keyblob64) {
596 error = "SSH2::userauth_pubkey: Wrong format of keyfile";
597 return -1;
598 }
599 keyblob64 += 8;
600 char *tmp = strchr(keyblob64, ' ');
601 if (!keyblob64) {
602 error = "SSH2::userauth_pubkey: Wrong format of keyfile";
603 return -1;
604 }
605
606 // eliminate icke@dort
607 *tmp = 0;
608
609
610 // First, send SERVICE_REQUEST for userauth
611 char preq[128], *ptr = preq;
612 preq[0] = SSH_MSG_SERVICE_REQUEST;
613 ++ptr;
614 *(u_int32_t*)ptr = htonl(12);
615 ptr += sizeof(u_int32_t);
616 memcpy(ptr, "ssh-userauth", 12);
617 ptr += 12;
618 packet_write(preq, ptr-preq);
619 if (packet_read(reply, sizeof(reply), &n) < 0)
620 return -1;
621 if (reply[0] != SSH_MSG_SERVICE_ACCEPT) {
622 error = "SSH2::userauth_passwd: 'ssh-userauth' message not accepted";
623 return -1;
624 }
625
626
627 // now send USERAUTH_REQUEST for ssh-connection
628 // service
629 size_t len = 1 + strlen(user) + 4 + strlen("ssh-connection") + 4 +
630 strlen("publickey") + 4 + 1 + strlen(keyblob64);
631 char *p = new char [len];
632 ptr = p;
633 *ptr = SSH_MSG_USERAUTH_REQUEST;
634 ++ptr;
635 *(u_int32_t*)ptr = htonl(l = strlen(user));
636 ptr += sizeof(u_int32_t);
637 memcpy(ptr, user, l);
638 ptr += l;
639
640 *(u_int32_t*)ptr = htonl(l = strlen("ssh-connection"));
641 ptr += sizeof(u_int32_t);
642 memcpy(ptr, "ssh-connection", l);
643 ptr += l;
644
645 *(u_int32_t*)ptr = htonl(l = strlen("publickey"));
646 ptr += sizeof(u_int32_t);
647 memcpy(ptr, "publickey", l);
648 ptr += l;
649
650 *ptr = 0; // FALSE
651 ++ptr;
652
653 *(u_int32_t*)ptr = htonl(l = strlen("ssh-rsa"));
654 ptr += sizeof(u_int32_t);
655 memcpy(ptr, "ssh-rsa", l);
656 ptr += l;
657
658 unsigned char *keyblob = new unsigned char [strlen(keyblob64)];
659 l = b64_pton(keyblob64, keyblob, strlen(keyblob64));
660 *(u_int32_t*)ptr = htonl(l);
661 ptr += sizeof(u_int32_t);
662 memcpy(ptr, keyblob, l);
663 packet_write(p, ptr-p+l);
664
665 delete [] p;
666 delete [] buf;
667 delete [] keyblob;
668
669 do {
670 if (packet_read(reply, sizeof(reply), &n) < 0)
671 return -1;
672 } while (reply[0] != SSH_MSG_USERAUTH_FAILURE &&
673 reply[0] != SSH_MSG_USERAUTH_PK_OK);
674
675 return (reply[0] == SSH_MSG_USERAUTH_FAILURE);
676}
677