comparison cli-authpubkey.c @ 45:9ee8996a375f

Pubkey auth is mostly there for the client. Something strange with remote hostkey verification though.
author Matt Johnston <matt@ucc.asn.au>
date Tue, 03 Aug 2004 17:26:56 +0000
parents
children 4b53a43f0082
comparison
equal deleted inserted replaced
44:45edf30ea0a6 45:9ee8996a375f
1 #include "includes.h"
2 #include "buffer.h"
3 #include "dbutil.h"
4 #include "session.h"
5 #include "ssh.h"
6 #include "runopts.h"
7 #include "auth.h"
8
9 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign);
10
11 /* Called when we receive a SSH_MSG_USERAUTH_FAILURE for a pubkey request.
12 * We use it to remove the key we tried from the list */
13 void cli_pubkeyfail() {
14
15 struct PubkeyList *keyitem;
16
17 TRACE(("enter cli_pubkeyfail"));
18 /* Find the key we failed with, and remove it */
19 for (keyitem = cli_ses.pubkeys; keyitem != NULL; keyitem = keyitem->next) {
20 if (keyitem->next == cli_ses.lastpubkey) {
21 keyitem->next = cli_ses.lastpubkey->next;
22 }
23 }
24
25 sign_key_free(cli_ses.lastpubkey->key); /* It won't be used again */
26 m_free(cli_ses.lastpubkey);
27 TRACE(("leave cli_pubkeyfail"));
28 }
29
30 void recv_msg_userauth_pk_ok() {
31
32 struct PubkeyList *keyitem;
33 buffer* keybuf;
34 char* algotype = NULL;
35 unsigned int algolen;
36 int keytype;
37 unsigned int remotelen;
38
39 TRACE(("enter recv_msg_userauth_pk_ok"));
40
41 algotype = buf_getstring(ses.payload, &algolen);
42 keytype = signkey_type_from_name(algotype, algolen);
43 m_free(algotype);
44
45 keybuf = buf_new(MAX_PUBKEY_SIZE);
46
47 remotelen = buf_getint(ses.payload);
48
49 /* Iterate through our keys, find which one it was that matched, and
50 * send a real request with that key */
51 for (keyitem = cli_ses.pubkeys; keyitem != NULL; keyitem = keyitem->next) {
52
53 if (keyitem->type != keytype) {
54 /* Types differed */
55 continue;
56 }
57
58 /* Now we compare the contents of the key */
59 keybuf->pos = keybuf->len = 0;
60 buf_put_pub_key(keybuf, keyitem->key, keytype);
61
62 if (keybuf->len != remotelen) {
63 /* Lengths differed */
64 continue;
65 }
66
67 if (memcmp(keybuf->data,
68 buf_getptr(ses.payload, remotelen), remotelen) != 0) {
69 /* Data didn't match this key */
70 continue;
71 }
72
73 /* Success */
74 break;
75 }
76
77 if (keyitem != NULL) {
78 TRACE(("matching key"));
79 /* XXX TODO: if it's an encrypted key, here we ask for their
80 * password */
81 send_msg_userauth_pubkey(keyitem->key, keytype, 1);
82 } else {
83 TRACE(("That was whacky. We got told that a key was valid, but it didn't match our list. Sounds like dodgy code on Dropbear's part"));
84 }
85
86 TRACE(("leave recv_msg_userauth_pk_ok"));
87 }
88
89 /* TODO: make it take an agent reference to use as well */
90 static void send_msg_userauth_pubkey(sign_key *key, int type, int realsign) {
91
92 const char *algoname = NULL;
93 int algolen;
94 buffer* sigbuf = NULL;
95
96 TRACE(("enter send_msg_userauth_pubkey"));
97 CHECKCLEARTOWRITE();
98
99 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_REQUEST);
100
101 buf_putstring(ses.writepayload, cli_opts.username,
102 strlen(cli_opts.username));
103
104 buf_putstring(ses.writepayload, SSH_SERVICE_CONNECTION,
105 SSH_SERVICE_CONNECTION_LEN);
106
107 buf_putstring(ses.writepayload, AUTH_METHOD_PUBKEY,
108 AUTH_METHOD_PUBKEY_LEN);
109
110 buf_putbyte(ses.writepayload, realsign);
111
112 algoname = signkey_name_from_type(type, &algolen);
113
114 buf_putstring(ses.writepayload, algoname, algolen);
115 buf_put_pub_key(ses.writepayload, key, type);
116
117 if (realsign) {
118 TRACE(("realsign"));
119 /* We put the signature as well - this contains string(session id), then
120 * the contents of the write payload to this point */
121 sigbuf = buf_new(4 + SHA1_HASH_SIZE + ses.writepayload->len);
122 buf_putstring(sigbuf, ses.session_id, SHA1_HASH_SIZE);
123 buf_putbytes(sigbuf, ses.writepayload->data, ses.writepayload->len);
124 buf_put_sign(ses.writepayload, key, type, sigbuf->data, sigbuf->len);
125 buf_free(sigbuf); /* Nothing confidential in the buffer */
126 }
127
128 encrypt_packet();
129 TRACE(("leave send_msg_userauth_pubkey"));
130 }
131
132 int cli_auth_pubkey() {
133
134 TRACE(("enter cli_auth_pubkey"));
135
136 if (cli_ses.pubkeys != NULL) {
137 /* Send a trial request */
138 send_msg_userauth_pubkey(cli_ses.pubkeys->key,
139 cli_ses.pubkeys->type, 0);
140 TRACE(("leave cli_auth_pubkey-success"));
141 return 1;
142 } else {
143 TRACE(("leave cli_auth_pubkey-failure"));
144 return 0;
145 }
146 }