comparison svr-authpubkey.c @ 1674:ba6fc7afe1c5

use sigtype where appropriate
author Matt Johnston <matt@ucc.asn.au>
date Mon, 06 Apr 2020 23:18:26 +0800
parents cc0fc5131c5c
children ae41624c2198
comparison
equal deleted inserted replaced
1668:49cb3cf4bd6f 1674:ba6fc7afe1c5
68 #if DROPBEAR_SVR_PUBKEY_AUTH 68 #if DROPBEAR_SVR_PUBKEY_AUTH
69 69
70 #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ 70 #define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */
71 #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */ 71 #define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */
72 72
73 static int checkpubkey(const char* algo, unsigned int algolen, 73 static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
74 const unsigned char* keyblob, unsigned int keybloblen); 74 const unsigned char* keyblob, unsigned int keybloblen);
75 static int checkpubkeyperms(void); 75 static int checkpubkeyperms(void);
76 static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen, 76 static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen,
77 const unsigned char* keyblob, unsigned int keybloblen); 77 const unsigned char* keyblob, unsigned int keybloblen);
78 static int checkfileperm(char * filename); 78 static int checkfileperm(char * filename);
79 79
80 /* process a pubkey auth request, sending success or failure message as 80 /* process a pubkey auth request, sending success or failure message as
81 * appropriate */ 81 * appropriate */
82 void svr_auth_pubkey(int valid_user) { 82 void svr_auth_pubkey(int valid_user) {
83 83
84 unsigned char testkey; /* whether we're just checking if a key is usable */ 84 unsigned char testkey; /* whether we're just checking if a key is usable */
85 char* algo = NULL; /* pubkey algo */ 85 char* sigalgo = NULL;
86 unsigned int algolen; 86 unsigned int sigalgolen;
87 const char* keyalgo;
88 unsigned int keyalgolen;
87 unsigned char* keyblob = NULL; 89 unsigned char* keyblob = NULL;
88 unsigned int keybloblen; 90 unsigned int keybloblen;
89 unsigned int sign_payload_length; 91 unsigned int sign_payload_length;
90 buffer * signbuf = NULL; 92 buffer * signbuf = NULL;
91 sign_key * key = NULL; 93 sign_key * key = NULL;
92 char* fp = NULL; 94 char* fp = NULL;
93 enum signkey_type type = -1; 95 enum signkey_type sigtype, keytype;
94 int auth_failure = 1; 96 int auth_failure = 1;
95 97
96 TRACE(("enter pubkeyauth")) 98 TRACE(("enter pubkeyauth"))
97 99
98 /* 0 indicates user just wants to check if key can be used, 1 is an 100 /* 0 indicates user just wants to check if key can be used, 1 is an
99 * actual attempt*/ 101 * actual attempt*/
100 testkey = (buf_getbool(ses.payload) == 0); 102 testkey = (buf_getbool(ses.payload) == 0);
101 103
102 algo = buf_getstring(ses.payload, &algolen); 104 sigalgo = buf_getstring(ses.payload, &sigalgolen);
105 sigtype = signature_type_from_name(sigalgo, sigalgolen);
106 keytype = signkey_type_from_signature(sigtype);
107 keyalgo = signkey_name_from_type(keytype, &keyalgolen);
108
103 keybloblen = buf_getint(ses.payload); 109 keybloblen = buf_getint(ses.payload);
104 keyblob = buf_getptr(ses.payload, keybloblen); 110 keyblob = buf_getptr(ses.payload, keybloblen);
105 111
106 if (!valid_user) { 112 if (!valid_user) {
107 /* Return failure once we have read the contents of the packet 113 /* Return failure once we have read the contents of the packet
115 if (svr_ses.plugin_instance != NULL) { 121 if (svr_ses.plugin_instance != NULL) {
116 char *options_buf; 122 char *options_buf;
117 if (svr_ses.plugin_instance->checkpubkey( 123 if (svr_ses.plugin_instance->checkpubkey(
118 svr_ses.plugin_instance, 124 svr_ses.plugin_instance,
119 &ses.plugin_session, 125 &ses.plugin_session,
120 algo, 126 keyalgo,
121 algolen, 127 keyalgolen,
122 keyblob, 128 keyblob,
123 keybloblen, 129 keybloblen,
124 ses.authstate.username) == DROPBEAR_SUCCESS) { 130 ses.authstate.username) == DROPBEAR_SUCCESS) {
125 /* Success */ 131 /* Success */
126 auth_failure = 0; 132 auth_failure = 0;
144 } 150 }
145 } 151 }
146 #endif 152 #endif
147 /* check if the key is valid */ 153 /* check if the key is valid */
148 if (auth_failure) { 154 if (auth_failure) {
149 auth_failure = checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE; 155 auth_failure = checkpubkey(keyalgo, keyalgolen, keyblob, keybloblen) == DROPBEAR_FAILURE;
150 } 156 }
151 157
152 if (auth_failure) { 158 if (auth_failure) {
153 send_msg_userauth_failure(0, 0); 159 send_msg_userauth_failure(0, 0);
154 goto out; 160 goto out;
155 } 161 }
156 162
157 /* let them know that the key is ok to use */ 163 /* let them know that the key is ok to use */
158 if (testkey) { 164 if (testkey) {
159 send_msg_userauth_pk_ok(algo, algolen, keyblob, keybloblen); 165 send_msg_userauth_pk_ok(sigalgo, sigalgolen, keyblob, keybloblen);
160 goto out; 166 goto out;
161 } 167 }
162 168
163 /* now we can actually verify the signature */ 169 /* now we can actually verify the signature */
164 170
165 /* get the key */ 171 /* get the key */
166 key = new_sign_key(); 172 key = new_sign_key();
167 type = DROPBEAR_SIGNKEY_ANY; 173 if (buf_get_pub_key(ses.payload, key, &keytype) == DROPBEAR_FAILURE) {
168 if (buf_get_pub_key(ses.payload, key, &type) == DROPBEAR_FAILURE) {
169 send_msg_userauth_failure(0, 1); 174 send_msg_userauth_failure(0, 1);
170 goto out; 175 goto out;
171 } 176 }
172 177
173 /* create the data which has been signed - this a string containing 178 /* create the data which has been signed - this a string containing
186 191
187 buf_setpos(signbuf, 0); 192 buf_setpos(signbuf, 0);
188 193
189 /* ... and finally verify the signature */ 194 /* ... and finally verify the signature */
190 fp = sign_key_fingerprint(keyblob, keybloblen); 195 fp = sign_key_fingerprint(keyblob, keybloblen);
191 if (buf_verify(ses.payload, key, signbuf) == DROPBEAR_SUCCESS) { 196 if (buf_verify(ses.payload, key, sigtype, signbuf) == DROPBEAR_SUCCESS) {
192 dropbear_log(LOG_NOTICE, 197 dropbear_log(LOG_NOTICE,
193 "Pubkey auth succeeded for '%s' with key %s from %s", 198 "Pubkey auth succeeded for '%s' with key %s from %s",
194 ses.authstate.pw_name, fp, svr_ses.addrstring); 199 ses.authstate.pw_name, fp, svr_ses.addrstring);
195 send_msg_userauth_success(); 200 send_msg_userauth_success();
196 #if DROPBEAR_PLUGIN 201 #if DROPBEAR_PLUGIN
211 out: 216 out:
212 /* cleanup stuff */ 217 /* cleanup stuff */
213 if (signbuf) { 218 if (signbuf) {
214 buf_free(signbuf); 219 buf_free(signbuf);
215 } 220 }
216 if (algo) { 221 if (sigalgo) {
217 m_free(algo); 222 m_free(sigalgo);
218 } 223 }
219 if (key) { 224 if (key) {
220 sign_key_free(key); 225 sign_key_free(key);
221 key = NULL; 226 key = NULL;
222 } 227 }
228 } 233 }
229 234
230 /* Reply that the key is valid for auth, this is sent when the user sends 235 /* Reply that the key is valid for auth, this is sent when the user sends
231 * a straight copy of their pubkey to test, to avoid having to perform 236 * a straight copy of their pubkey to test, to avoid having to perform
232 * expensive signing operations with a worthless key */ 237 * expensive signing operations with a worthless key */
233 static void send_msg_userauth_pk_ok(const char* algo, unsigned int algolen, 238 static void send_msg_userauth_pk_ok(const char* sigalgo, unsigned int sigalgolen,
234 const unsigned char* keyblob, unsigned int keybloblen) { 239 const unsigned char* keyblob, unsigned int keybloblen) {
235 240
236 TRACE(("enter send_msg_userauth_pk_ok")) 241 TRACE(("enter send_msg_userauth_pk_ok"))
237 CHECKCLEARTOWRITE(); 242 CHECKCLEARTOWRITE();
238 243
239 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK); 244 buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK);
240 buf_putstring(ses.writepayload, algo, algolen); 245 buf_putstring(ses.writepayload, sigalgo, sigalgolen);
241 buf_putstring(ses.writepayload, (const char*)keyblob, keybloblen); 246 buf_putstring(ses.writepayload, (const char*)keyblob, keybloblen);
242 247
243 encrypt_packet(); 248 encrypt_packet();
244 TRACE(("leave send_msg_userauth_pk_ok")) 249 TRACE(("leave send_msg_userauth_pk_ok"))
245 250
352 357
353 358
354 /* Checks whether a specified publickey (and associated algorithm) is an 359 /* Checks whether a specified publickey (and associated algorithm) is an
355 * acceptable key for authentication */ 360 * acceptable key for authentication */
356 /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ 361 /* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */
357 static int checkpubkey(const char* algo, unsigned int algolen, 362 static int checkpubkey(const char* keyalgo, unsigned int keyalgolen,
358 const unsigned char* keyblob, unsigned int keybloblen) { 363 const unsigned char* keyblob, unsigned int keybloblen) {
359 364
360 FILE * authfile = NULL; 365 FILE * authfile = NULL;
361 char * filename = NULL; 366 char * filename = NULL;
362 int ret = DROPBEAR_FAILURE; 367 int ret = DROPBEAR_FAILURE;
366 uid_t origuid; 371 uid_t origuid;
367 gid_t origgid; 372 gid_t origgid;
368 373
369 TRACE(("enter checkpubkey")) 374 TRACE(("enter checkpubkey"))
370 375
371 /* check that we can use the algo */
372 if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) {
373 dropbear_log(LOG_WARNING,
374 "Pubkey auth attempt with unknown algo for '%s' from %s",
375 ses.authstate.pw_name, svr_ses.addrstring);
376 goto out;
377 }
378
379 /* check file permissions, also whether file exists */ 376 /* check file permissions, also whether file exists */
380 if (checkpubkeyperms() == DROPBEAR_FAILURE) { 377 if (checkpubkeyperms() == DROPBEAR_FAILURE) {
381 TRACE(("bad authorized_keys permissions, or file doesn't exist")) 378 TRACE(("bad authorized_keys permissions, or file doesn't exist"))
382 goto out; 379 goto out;
383 } 380 }
425 TRACE(("checkpubkey: authorized_keys EOF reached")) 422 TRACE(("checkpubkey: authorized_keys EOF reached"))
426 break; 423 break;
427 } 424 }
428 line_num++; 425 line_num++;
429 426
430 ret = checkpubkey_line(line, line_num, filename, algo, algolen, keyblob, keybloblen); 427 ret = checkpubkey_line(line, line_num, filename, keyalgo, keyalgolen, keyblob, keybloblen);
431 if (ret == DROPBEAR_SUCCESS) { 428 if (ret == DROPBEAR_SUCCESS) {
432 break; 429 break;
433 } 430 }
434 431
435 /* We continue to the next line otherwise */ 432 /* We continue to the next line otherwise */