1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Dropbear - a SSH2 server 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Copyright (c) 2002,2003 Matt Johnston 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * All rights reserved. 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Permission is hereby granted, free of charge, to any person obtaining a copy 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * of this software and associated documentation files (the "Software"), to deal 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * in the Software without restriction, including without limitation the rights 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * copies of the Software, and to permit persons to whom the Software is 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * furnished to do so, subject to the following conditions: 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The above copyright notice and this permission notice shall be included in 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * all copies or substantial portions of the Software. 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * SOFTWARE. */ 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Process a pubkey auth request */ 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "includes.h" 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "session.h" 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "dbutil.h" 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "buffer.h" 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "signkey.h" 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "auth.h" 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "ssh.h" 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "packet.h" 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "algo.h" 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef ENABLE_SVR_PUBKEY_AUTH 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define MIN_AUTHKEYS_LINE 10 /* "ssh-rsa AB" - short but doesn't matter */ 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define MAX_AUTHKEYS_LINE 4200 /* max length of a line in authkeys */ 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int checkpubkey(unsigned char* algo, unsigned int algolen, 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* keyblob, unsigned int keybloblen); 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int checkpubkeyperms(); 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_userauth_pk_ok(unsigned char* algo, unsigned int algolen, 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* keyblob, unsigned int keybloblen); 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int checkfileperm(char * filename); 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* process a pubkey auth request, sending success or failure message as 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * appropriate */ 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectvoid svr_auth_pubkey() { 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char testkey; /* whether we're just checking if a key is usable */ 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* algo = NULL; /* pubkey algo */ 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int algolen; 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* keyblob = NULL; 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int keybloblen; 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * signbuf = NULL; 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key * key = NULL; 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char* fp = NULL; 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int type = -1; 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("enter pubkeyauth")) 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* 0 indicates user just wants to check if key can be used, 1 is an 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * actual attempt*/ 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project testkey = (buf_getbool(ses.payload) == 0); 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project algo = buf_getstring(ses.payload, &algolen); 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keybloblen = buf_getint(ses.payload); 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project keyblob = buf_getptr(ses.payload, keybloblen); 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check if the key is valid */ 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (checkpubkey(algo, algolen, keyblob, keybloblen) == DROPBEAR_FAILURE) { 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project send_msg_userauth_failure(0, 0); 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* let them know that the key is ok to use */ 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (testkey) { 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project send_msg_userauth_pk_ok(algo, algolen, keyblob, keybloblen); 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now we can actually verify the signature */ 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* get the key */ 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project key = new_sign_key(); 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project type = DROPBEAR_SIGNKEY_ANY; 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_get_pub_key(ses.payload, key, &type) == DROPBEAR_FAILURE) { 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project send_msg_userauth_failure(0, 1); 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* create the data which has been signed - this a string containing 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * session_id, concatenated with the payload packet up to the signature */ 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project signbuf = buf_new(ses.payload->pos + 4 + SHA1_HASH_SIZE); 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(signbuf, ses.session_id, SHA1_HASH_SIZE); 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbytes(signbuf, ses.payload->data, ses.payload->pos); 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(signbuf, 0); 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* ... and finally verify the signature */ 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fp = sign_key_fingerprint(keyblob, keybloblen); 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_verify(ses.payload, key, buf_getptr(signbuf, signbuf->len), 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project signbuf->len) == DROPBEAR_SUCCESS) { 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_log(LOG_NOTICE, 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "pubkey auth succeeded for '%s' with key %s from %s", 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.authstate.printableuser, fp, svr_ses.addrstring); 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project send_msg_userauth_success(); 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_log(LOG_WARNING, 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "pubkey auth bad signature for '%s' with key %s from %s", 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.authstate.printableuser, fp, svr_ses.addrstring); 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project send_msg_userauth_failure(0, 1); 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(fp); 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout: 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* cleanup stuff */ 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (signbuf) { 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(signbuf); 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (algo) { 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(algo); 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (key) { 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project sign_key_free(key); 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project key = NULL; 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave pubkeyauth")) 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Reply that the key is valid for auth, this is sent when the user sends 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * a straight copy of their pubkey to test, to avoid having to perform 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * expensive signing operations with a worthless key */ 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic void send_msg_userauth_pk_ok(unsigned char* algo, unsigned int algolen, 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* keyblob, unsigned int keybloblen) { 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("enter send_msg_userauth_pk_ok")) 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project CHECKCLEARTOWRITE(); 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putbyte(ses.writepayload, SSH_MSG_USERAUTH_PK_OK); 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(ses.writepayload, algo, algolen); 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_putstring(ses.writepayload, keyblob, keybloblen); 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project encrypt_packet(); 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave send_msg_userauth_pk_ok")) 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Checks whether a specified publickey (and associated algorithm) is an 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * acceptable key for authentication */ 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Returns DROPBEAR_SUCCESS if key is ok for auth, DROPBEAR_FAILURE otherwise */ 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int checkpubkey(unsigned char* algo, unsigned int algolen, 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char* keyblob, unsigned int keybloblen) { 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project FILE * authfile = NULL; 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char * filename = NULL; 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret = DROPBEAR_FAILURE; 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buffer * line = NULL; 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int len, pos; 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("enter checkpubkey")) 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check that we can use the algo */ 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (have_algo(algo, algolen, sshhostkey) == DROPBEAR_FAILURE) { 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_log(LOG_WARNING, 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project "pubkey auth attempt with unknown algo for '%s' from %s", 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.authstate.printableuser, svr_ses.addrstring); 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check file permissions, also whether file exists */ 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (checkpubkeyperms() == DROPBEAR_FAILURE) { 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("bad authorized_keys permissions, or file doesn't exist")) 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* we don't need to check pw and pw_dir for validity, since 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * its been done in checkpubkeyperms. */ 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = strlen(ses.authstate.pw->pw_dir); 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate max required pathname storage, 183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */ 184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project filename = m_malloc(len + 22); 185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project snprintf(filename, len + 22, "%s/.ssh/authorized_keys", 186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.authstate.pw->pw_dir); 187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* open the file */ 189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project authfile = fopen(filename, "r"); 190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (authfile == NULL) { 191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("checkpubkey: opened authorized_keys OK")) 194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project line = buf_new(MAX_AUTHKEYS_LINE); 196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* iterate through the lines */ 198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project do { 199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getline(line, authfile) == DROPBEAR_FAILURE) { 201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* EOF reached */ 202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("checkpubkey: authorized_keys EOF reached")) 203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (line->len < MIN_AUTHKEYS_LINE) { 207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("checkpubkey: line too short")) 208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; /* line is too short for it to be a valid key */ 209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check the key type - this also stops us from using keys 212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * which have options with them */ 213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (strncmp(buf_getptr(line, algolen), algo, algolen) != 0) { 214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_incrpos(line, algolen); 217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check for space (' ') character */ 219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getbyte(line) != ' ') { 220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("checkpubkey: space character expected, isn't there")) 221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project continue; 222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* truncate the line at the space after the base64 data */ 225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pos = line->pos; 226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (len = 0; line->pos < line->len; len++) { 227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (buf_getbyte(line) == ' ') break; 228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setpos(line, pos); 230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_setlen(line, line->pos + len); 231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("checkpubkey: line pos = %d len = %d", line->pos, line->len)) 233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = cmp_base64_key(keyblob, keybloblen, algo, algolen, line, NULL); 235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ret == DROPBEAR_SUCCESS) { 236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project break; 237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* We continue to the next line otherwise */ 240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } while (1); 242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout: 244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (authfile) { 245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project fclose(authfile); 246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (line) { 248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project buf_free(line); 249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(filename); 251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave checkpubkey: ret=%d", ret)) 252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Returns DROPBEAR_SUCCESS if file permissions for pubkeys are ok, 257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * DROPBEAR_FAILURE otherwise. 258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Checks that the user's homedir, ~/.ssh, and 259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * ~/.ssh/authorized_keys are all owned by either root or the user, and are 260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * g-w, o-w */ 261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int checkpubkeyperms() { 262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project char* filename = NULL; 264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int ret = DROPBEAR_FAILURE; 265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned int len; 266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("enter checkpubkeyperms")) 268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ses.authstate.pw->pw_dir == NULL) { 270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((len = strlen(ses.authstate.pw->pw_dir)) == 0) { 274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate max required pathname storage, 278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * = path + "/.ssh/authorized_keys" + '\0' = pathlen + 22 */ 279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project filename = m_malloc(len + 22); 280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project strncpy(filename, ses.authstate.pw->pw_dir, len+1); 281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check ~ */ 283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (checkfileperm(filename) != DROPBEAR_SUCCESS) { 284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check ~/.ssh */ 288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project strncat(filename, "/.ssh", 5); /* strlen("/.ssh") == 5 */ 289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (checkfileperm(filename) != DROPBEAR_SUCCESS) { 290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now check ~/.ssh/authorized_keys */ 294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project strncat(filename, "/authorized_keys", 16); 295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (checkfileperm(filename) != DROPBEAR_SUCCESS) { 296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto out; 297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* file looks ok, return success */ 300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ret = DROPBEAR_SUCCESS; 301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectout: 303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project m_free(filename); 304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave checkpubkeyperms")) 306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return ret; 307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Checks that a file is owned by the user or root, and isn't writable by 310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * group or other */ 311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ 312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int checkfileperm(char * filename) { 313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project struct stat filestat; 314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int badperm = 0; 315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("enter checkfileperm(%s)", filename)) 317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (stat(filename, &filestat) != 0) { 319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave checkfileperm: stat() != 0")) 320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return DROPBEAR_FAILURE; 321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check ownership - user or root only*/ 323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (filestat.st_uid != ses.authstate.pw->pw_uid 324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project && filestat.st_uid != 0) { 325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project badperm = 1; 326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("wrong ownership")) 327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check permissions - don't want group or others +w */ 329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (filestat.st_mode & (S_IWGRP | S_IWOTH)) { 330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project badperm = 1; 331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("wrong perms")) 332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (badperm) { 334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (!ses.authstate.perm_warn) { 335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ses.authstate.perm_warn = 1; 336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project dropbear_log(LOG_INFO, "%s must be owned by user or root, and not writable by others", filename); 337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave checkfileperm: failure perms/owner")) 339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return DROPBEAR_FAILURE; 340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project TRACE(("leave checkfileperm: success")) 343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return DROPBEAR_SUCCESS; 344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 348