# # Port from ldappubkey-ossh3.8.1p1-v201.patch (www.b0l.org) # Tested on OpenSSH 3.9 (OpenBSD version) OpenBSD 3.6/3.7 (default install) OpenLDAP 2.1.30 (from ports) # Added: lpkUserFilter, lpkGroupFilter (default values are hardcoded) # Removed: ldap_ssl, ldap_tls (if needed, SSL can be done with other software) # Auth: Maxim Bourmistrov, maximATchl.chalmers.se # # Requirements: OpenLDAP # diff -ruN ssh.orig/Makefile.inc ssh/Makefile.inc --- ssh.orig/Makefile.inc Thu Mar 24 22:02:07 2005 +++ ssh/Makefile.inc Thu Mar 24 22:31:31 2005 @@ -1,22 +1,25 @@ -# $OpenBSD: Makefile.inc,v 1.29 2004/06/21 18:34:51 avsm Exp $ +# $OpenBSD: Makefile.inc,v 1.29 2004/06/21 18:34:51 avsm Exp $ -CFLAGS+= -I${.CURDIR}/.. +CFLAGS+= -I${.CURDIR}/.. -CDIAGFLAGS= -Wall -#CDIAGFLAGS+= -Werror -CDIAGFLAGS+= -Wpointer-arith -CDIAGFLAGS+= -Wno-uninitialized -#CDIAGFLAGS+= -Wstrict-prototypes -CDIAGFLAGS+= -Wmissing-prototypes -CDIAGFLAGS+= -Wunused -#CDIAGFLAGS+= -Wsign-compare -CDIAGFLAGS+= -Wbounded -#CDIAGFLAGS+= -Wshadow +CDIAGFLAGS= -Wall +#CDIAGFLAGS+= -Werror +CDIAGFLAGS+= -Wpointer-arith +CDIAGFLAGS+= -Wno-uninitialized +#CDIAGFLAGS+= -Wstrict-prototypes +CDIAGFLAGS+= -Wmissing-prototypes +CDIAGFLAGS+= -Wunused +#CDIAGFLAGS+= -Wsign-compare +CDIAGFLAGS+= -Wbounded +#CDIAGFLAGS+= -Wshadow #DEBUG=-g -#CFLAGS+= -DSMARTCARD -#LDADD+= -lsectok +#CFLAGS+= -DSMARTCARD +#LDADD+= -lsectok + +CFLAGS+= -I/usr/local/include -DWITH_LDAP_PUBKEY +LDADD+= -L/usr/local/lib -llber -lldap .include diff -ruN ssh.orig/auth-rsa.c ssh/auth-rsa.c --- ssh.orig/auth-rsa.c Thu Mar 24 22:02:07 2005 +++ ssh/auth-rsa.c Thu Mar 24 22:55:24 2005 @@ -57,53 +57,53 @@ BIGNUM * auth_rsa_generate_challenge(Key *key) { - BIGNUM *challenge; - BN_CTX *ctx; + BIGNUM *challenge; + BN_CTX *ctx; - if ((challenge = BN_new()) == NULL) - fatal("auth_rsa_generate_challenge: BN_new() failed"); - /* Generate a random challenge. */ - BN_rand(challenge, 256, 0, 0); - if ((ctx = BN_CTX_new()) == NULL) - fatal("auth_rsa_generate_challenge: BN_CTX_new() failed"); - BN_mod(challenge, challenge, key->rsa->n, ctx); - BN_CTX_free(ctx); + if ((challenge = BN_new()) == NULL) + fatal("auth_rsa_generate_challenge: BN_new() failed"); + /* Generate a random challenge. */ + BN_rand(challenge, 256, 0, 0); + if ((ctx = BN_CTX_new()) == NULL) + fatal("auth_rsa_generate_challenge: BN_CTX_new() failed"); + BN_mod(challenge, challenge, key->rsa->n, ctx); + BN_CTX_free(ctx); - return challenge; + return challenge; } int auth_rsa_verify_response(Key *key, BIGNUM *challenge, u_char response[16]) { - u_char buf[32], mdbuf[16]; - MD5_CTX md; - int len; + u_char buf[32], mdbuf[16]; + MD5_CTX md; + int len; - /* don't allow short keys */ - if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits", - BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); - return (0); - } + /* don't allow short keys */ + if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { + error("auth_rsa_verify_response: RSA modulus too small: %d < minimum %d bits", + BN_num_bits(key->rsa->n), SSH_RSA_MINIMUM_MODULUS_SIZE); + return (0); + } - /* The response is MD5 of decrypted challenge plus session id. */ - len = BN_num_bytes(challenge); - if (len <= 0 || len > 32) - fatal("auth_rsa_verify_response: bad challenge length %d", len); - memset(buf, 0, 32); - BN_bn2bin(challenge, buf + 32 - len); - MD5_Init(&md); - MD5_Update(&md, buf, 32); - MD5_Update(&md, session_id, 16); - MD5_Final(mdbuf, &md); + /* The response is MD5 of decrypted challenge plus session id. */ + len = BN_num_bytes(challenge); + if (len <= 0 || len > 32) + fatal("auth_rsa_verify_response: bad challenge length %d", len); + memset(buf, 0, 32); + BN_bn2bin(challenge, buf + 32 - len); + MD5_Init(&md); + MD5_Update(&md, buf, 32); + MD5_Update(&md, session_id, 16); + MD5_Final(mdbuf, &md); - /* Verify that the response is the original challenge. */ - if (memcmp(response, mdbuf, 16) != 0) { - /* Wrong answer. */ - return (0); - } - /* Correct answer. */ - return (1); + /* Verify that the response is the original challenge. */ + if (memcmp(response, mdbuf, 16) != 0) { + /* Wrong answer. */ + return (0); + } + /* Correct answer. */ + return (1); } /* @@ -115,34 +115,34 @@ int auth_rsa_challenge_dialog(Key *key) { - BIGNUM *challenge, *encrypted_challenge; - u_char response[16]; - int i, success; + BIGNUM *challenge, *encrypted_challenge; + u_char response[16]; + int i, success; - if ((encrypted_challenge = BN_new()) == NULL) - fatal("auth_rsa_challenge_dialog: BN_new() failed"); + if ((encrypted_challenge = BN_new()) == NULL) + fatal("auth_rsa_challenge_dialog: BN_new() failed"); - challenge = PRIVSEP(auth_rsa_generate_challenge(key)); + challenge = PRIVSEP(auth_rsa_generate_challenge(key)); - /* Encrypt the challenge with the public key. */ - rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); + /* Encrypt the challenge with the public key. */ + rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); - /* Send the encrypted challenge to the client. */ - packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); - packet_put_bignum(encrypted_challenge); - packet_send(); - BN_clear_free(encrypted_challenge); - packet_write_wait(); + /* Send the encrypted challenge to the client. */ + packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); + packet_put_bignum(encrypted_challenge); + packet_send(); + BN_clear_free(encrypted_challenge); + packet_write_wait(); - /* Wait for a response. */ - packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); - for (i = 0; i < 16; i++) - response[i] = packet_get_char(); - packet_check_eom(); + /* Wait for a response. */ + packet_read_expect(SSH_CMSG_AUTH_RSA_RESPONSE); + for (i = 0; i < 16; i++) + response[i] = packet_get_char(); + packet_check_eom(); - success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); - BN_clear_free(challenge); - return (success); + success = PRIVSEP(auth_rsa_verify_response(key, challenge, response)); + BN_clear_free(challenge); + return (success); } /* @@ -153,127 +153,225 @@ int auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) { - char line[SSH_MAX_PUBKEY_BYTES], *file; - int allowed = 0; - u_int bits; - FILE *f; - u_long linenum = 0; - struct stat st; - Key *key; + char line[SSH_MAX_PUBKEY_BYTES], *file; + int allowed = 0; + u_int bits; + FILE *f; + u_long linenum = 0; + struct stat st; + Key *key; - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); +#ifdef WITH_LDAP_PUBKEY + lh_t host; + pkdata **data = NULL; + int i = 0; +#endif - /* The authorized keys. */ - file = authorized_keys_file(pw); - debug("trying public RSA key file %s", file); + /* Temporarily use the user's uid. */ + temporarily_use_uid(pw); - /* Fail quietly if file does not exist */ - if (stat(file, &st) < 0) { - /* Restore the privileged uid. */ - restore_uid(); - xfree(file); - return (0); - } - /* Open the file containing the authorized keys. */ - f = fopen(file, "r"); - if (!f) { - /* Restore the privileged uid. */ - restore_uid(); - xfree(file); - return (0); - } - if (options.strict_modes && - secure_filename(f, file, pw, line, sizeof(line)) != 0) { - xfree(file); - fclose(f); - logit("Authentication refused: %s", line); - restore_uid(); - return (0); - } +#ifdef WITH_LDAP_PUBKEY - /* Flag indicating whether the key is allowed. */ - allowed = 0; + /* JUST HERE HACK HACK */ + key = key_new(KEY_RSA1); - key = key_new(KEY_RSA1); + debug("[LDAP] trying to get RSA1 key"); - /* - * Go though the accepted keys, looking for the current key. If - * found, perform a challenge-response dialog to verify that the - * user really has the corresponding private key. - */ - while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { - char *cp; - char *key_options; + /* lets get the identity.pub from the ldap server */ + /* i must fill Key *key with the read key struct */ + host.lpkuurl = options.lpk_opt.lpk_user_server; + host.lpkufltr = options.lpk_opt.lpk_user_filter; + host.lpkgurl = options.lpk_opt.lpk_group_server; + host.lpkgfltr = options.lpk_opt.lpk_group_filter; + host.lpkbd = options.lpk_opt.lpk_binddn; + host.lpkbp = options.lpk_opt.lpk_bindpw; + host.lpksg = options.lpk_opt.lpk_srvgrp; - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; + /* if(options.myldap_opt.pubkey_from_ldap && key_ldap_read(key, pw->pw_name, &host) != 1) { */ + if(options.lpk_opt.lpk_on && (data = get_ldap_data(&host, pw)) ) { + debug("LDAP pubkey failed!!\n"); + debug("User URL: %s !!", options.lpk_opt.lpk_user_server); + } - /* - * Check if there are options for this key, and if so, - * save their starting address and skip the option part - * for now. If there are no options, set the starting - * address to NULL. - */ - if (*cp < '0' || *cp > '9') { - int quoted = 0; - key_options = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - } else - key_options = NULL; + if (data) + while(data[i] != NULL) { + char *cp, *options; - /* Parse the key from the line. */ - if (hostfile_read_key(&cp, &bits, key) == 0) { - debug("%.100s, line %lu: non ssh1 key syntax", - file, linenum); - continue; - } - /* cp now points to the comment part. */ + for (cp = (char *)data[i++]->bv_val; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; - /* Check if the we have found the desired key (identified by its modulus). */ - if (BN_cmp(key->rsa->n, client_n) != 0) - continue; + /* + * Check if there are options for this key, and if so, + * save their starting address and skip the option part + * for now. If there are no options, set the starting + * address to NULL. + */ + if (*cp < '0' || *cp > '9') { + int quoted = 0; + options = cp; + for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { + if (*cp == '\\' && cp[1] == '"') + cp++; /* Skip both */ + else if (*cp == '"') + quoted = !quoted; + } + } else + options = NULL; - /* check the real bits */ - if (bits != BN_num_bits(key->rsa->n)) - logit("Warning: %s, line %lu: keysize mismatch: " - "actual %d vs. announced %d.", - file, linenum, BN_num_bits(key->rsa->n), bits); + /* Parse the key from the line. */ + if (hostfile_read_key(&cp, &bits, key) == 0) { + debug("[LDAP] line %d: non ssh1 key syntax", i); + continue; + } + /* cp now points to the comment part. */ - /* We have found the desired key. */ - /* - * If our options do not allow this key to be used, - * do not send challenge. - */ - if (!auth_parse_options(pw, key_options, file, linenum)) - continue; + /* Check if the we have found the desired key (identified by its modulus). */ + if (BN_cmp(key->rsa->n, client_n) != 0) + continue; - /* break out, this key is allowed */ - allowed = 1; - break; - } + /* check the real bits */ + if (bits != BN_num_bits(key->rsa->n)) + logit("[LDAP] Warning: ldap, line %lu: keysize mismatch: " + "actual %d vs. announced %d.", (unsigned long)i, BN_num_bits(key->rsa->n), bits); - /* Restore the privileged uid. */ - restore_uid(); + /* We have found the desired key. */ + /* + * If our options do not allow this key to be used, + * do not send challenge. + */ + if (!auth_parse_options(pw, options, "[LDAP]", (unsigned long) i)) + continue; - /* Close the file. */ - xfree(file); - fclose(f); + /* break out, this key is allowed */ + allowed = 1; - /* return key if allowed */ - if (allowed && rkey != NULL) - *rkey = key; - else - key_free(key); - return (allowed); + /* add the return stuff etc... */ + /* Restore the privileged uid. */ + restore_uid(); + + /* return key if allowed */ + if (allowed && rkey != NULL) + *rkey = key; + else + key_free(key); + + ldap_value_free_len(data); + return (allowed); + } +#endif + + /* The authorized keys. */ + file = authorized_keys_file(pw); + debug("trying public RSA key file %s", file); + + /* Fail quietly if file does not exist */ + if (stat(file, &st) < 0) { + /* Restore the privileged uid. */ + restore_uid(); + xfree(file); + return (0); + } + /* Open the file containing the authorized keys. */ + f = fopen(file, "r"); + if (!f) { + /* Restore the privileged uid. */ + restore_uid(); + xfree(file); + return (0); + } + if (options.strict_modes && + secure_filename(f, file, pw, line, sizeof(line)) != 0) { + xfree(file); + fclose(f); + logit("Authentication refused: %s", line); + restore_uid(); + return (0); + } + + /* Flag indicating whether the key is allowed. */ + allowed = 0; + + key = key_new(KEY_RSA1); + + /* + * Go though the accepted keys, looking for the current key. If + * found, perform a challenge-response dialog to verify that the + * user really has the corresponding private key. + */ + while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { + char *cp; + char *key_options; + + /* Skip leading whitespace, empty and comment lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + + /* + * Check if there are options for this key, and if so, + * save their starting address and skip the option part + * for now. If there are no options, set the starting + * address to NULL. + */ + if (*cp < '0' || *cp > '9') { + int quoted = 0; + key_options = cp; + for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { + if (*cp == '\\' && cp[1] == '"') + cp++; /* Skip both */ + else if (*cp == '"') + quoted = !quoted; + } + } else + key_options = NULL; + + /* Parse the key from the line. */ + if (hostfile_read_key(&cp, &bits, key) == 0) { + debug("%.100s, line %lu: non ssh1 key syntax", + file, linenum); + continue; + } + /* cp now points to the comment part. */ + + /* Check if the we have found the desired key (identified by its modulus). */ + if (BN_cmp(key->rsa->n, client_n) != 0) + continue; + + /* check the real bits */ + if (bits != BN_num_bits(key->rsa->n)) + logit("Warning: %s, line %lu: keysize mismatch: " + "actual %d vs. announced %d.", + file, linenum, BN_num_bits(key->rsa->n), bits); + + /* We have found the desired key. */ + /* + * If our options do not allow this key to be used, + * do not send challenge. + */ + if (!auth_parse_options(pw, key_options, file, linenum)) + continue; + + /* break out, this key is allowed */ + allowed = 1; + break; + } + + /* Restore the privileged uid. */ + restore_uid(); + + /* Close the file. */ + xfree(file); + fclose(f); + + /* return key if allowed */ + if (allowed && rkey != NULL) + *rkey = key; + else + key_free(key); + return (allowed); } /* @@ -284,43 +382,43 @@ int auth_rsa(Authctxt *authctxt, BIGNUM *client_n) { - Key *key; - char *fp; - struct passwd *pw = authctxt->pw; + Key *key; + char *fp; + struct passwd *pw = authctxt->pw; - /* no user given */ - if (!authctxt->valid) - return 0; + /* no user given */ + if (!authctxt->valid) + return 0; - if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) { - auth_clear_options(); - return (0); - } + if (!PRIVSEP(auth_rsa_key_allowed(pw, client_n, &key))) { + auth_clear_options(); + return (0); + } - /* Perform the challenge-response dialog for this key. */ - if (!auth_rsa_challenge_dialog(key)) { - /* Wrong response. */ - verbose("Wrong response to RSA authentication challenge."); - packet_send_debug("Wrong response to RSA authentication challenge."); - /* - * Break out of the loop. Otherwise we might send - * another challenge and break the protocol. - */ - key_free(key); - return (0); - } - /* - * Correct response. The client has been successfully - * authenticated. Note that we have not yet processed the - * options; this will be reset if the options cause the - * authentication to be rejected. - */ - fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(key), fp); - xfree(fp); - key_free(key); + /* Perform the challenge-response dialog for this key. */ + if (!auth_rsa_challenge_dialog(key)) { + /* Wrong response. */ + verbose("Wrong response to RSA authentication challenge."); + packet_send_debug("Wrong response to RSA authentication challenge."); + /* + * Break out of the loop. Otherwise we might send + * another challenge and break the protocol. + */ + key_free(key); + return (0); + } + /* + * Correct response. The client has been successfully + * authenticated. Note that we have not yet processed the + * options; this will be reset if the options cause the + * authentication to be rejected. + */ + fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(key), fp); + xfree(fp); + key_free(key); - packet_send_debug("RSA authentication accepted."); - return (1); + packet_send_debug("RSA authentication accepted."); + return (1); } diff -ruN ssh.orig/auth2-pubkey.c ssh/auth2-pubkey.c --- ssh.orig/auth2-pubkey.c Thu Mar 24 22:02:07 2005 +++ ssh/auth2-pubkey.c Fri Mar 25 17:30:03 2005 @@ -51,228 +51,308 @@ static int userauth_pubkey(Authctxt *authctxt) { - Buffer b; - Key *key = NULL; - char *pkalg; - u_char *pkblob, *sig; - u_int alen, blen, slen; - int have_sig, pktype; - int authenticated = 0; + Buffer b; + Key *key = NULL; + char *pkalg; + u_char *pkblob, *sig; + u_int alen, blen, slen; + int have_sig, pktype; + int authenticated = 0; - if (!authctxt->valid) { - debug2("userauth_pubkey: disabled because of invalid user"); - return 0; - } - have_sig = packet_get_char(); - if (datafellows & SSH_BUG_PKAUTH) { - debug2("userauth_pubkey: SSH_BUG_PKAUTH"); - /* no explicit pkalg given */ - pkblob = packet_get_string(&blen); - buffer_init(&b); - buffer_append(&b, pkblob, blen); - /* so we have to extract the pkalg from the pkblob */ - pkalg = buffer_get_string(&b, &alen); - buffer_free(&b); - } else { - pkalg = packet_get_string(&alen); - pkblob = packet_get_string(&blen); - } - pktype = key_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) { - /* this is perfectly legal */ - logit("userauth_pubkey: unsupported public key algorithm: %s", - pkalg); - goto done; - } - key = key_from_blob(pkblob, blen); - if (key == NULL) { - error("userauth_pubkey: cannot decode key: %s", pkalg); - goto done; - } - if (key->type != pktype) { - error("userauth_pubkey: type mismatch for decoded key " - "(received %d, expected %d)", key->type, pktype); - goto done; - } - if (have_sig) { - sig = packet_get_string(&slen); - packet_check_eom(); - buffer_init(&b); - if (datafellows & SSH_OLD_SESSIONID) { - buffer_append(&b, session_id2, session_id2_len); - } else { - buffer_put_string(&b, session_id2, session_id2_len); - } - /* reconstruct packet */ - buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); - buffer_put_cstring(&b, authctxt->user); - buffer_put_cstring(&b, - datafellows & SSH_BUG_PKSERVICE ? - "ssh-userauth" : - authctxt->service); - if (datafellows & SSH_BUG_PKAUTH) { - buffer_put_char(&b, have_sig); - } else { - buffer_put_cstring(&b, "publickey"); - buffer_put_char(&b, have_sig); - buffer_put_cstring(&b, pkalg); - } - buffer_put_string(&b, pkblob, blen); + if (!authctxt->valid) { + debug2("userauth_pubkey: disabled because of invalid user"); + return 0; + } + have_sig = packet_get_char(); + if (datafellows & SSH_BUG_PKAUTH) { + debug2("userauth_pubkey: SSH_BUG_PKAUTH"); + /* no explicit pkalg given */ + pkblob = packet_get_string(&blen); + buffer_init(&b); + buffer_append(&b, pkblob, blen); + /* so we have to extract the pkalg from the pkblob */ + pkalg = buffer_get_string(&b, &alen); + buffer_free(&b); + } else { + pkalg = packet_get_string(&alen); + pkblob = packet_get_string(&blen); + } + pktype = key_type_from_name(pkalg); + if (pktype == KEY_UNSPEC) { + /* this is perfectly legal */ + logit("userauth_pubkey: unsupported public key algorithm: %s", + pkalg); + goto done; + } + key = key_from_blob(pkblob, blen); + if (key == NULL) { + error("userauth_pubkey: cannot decode key: %s", pkalg); + goto done; + } + if (key->type != pktype) { + error("userauth_pubkey: type mismatch for decoded key " + "(received %d, expected %d)", key->type, pktype); + goto done; + } + if (have_sig) { + sig = packet_get_string(&slen); + packet_check_eom(); + buffer_init(&b); + if (datafellows & SSH_OLD_SESSIONID) { + buffer_append(&b, session_id2, session_id2_len); + } else { + buffer_put_string(&b, session_id2, session_id2_len); + } + /* reconstruct packet */ + buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); + buffer_put_cstring(&b, authctxt->user); + buffer_put_cstring(&b, + datafellows & SSH_BUG_PKSERVICE ? + "ssh-userauth" : + authctxt->service); + if (datafellows & SSH_BUG_PKAUTH) { + buffer_put_char(&b, have_sig); + } else { + buffer_put_cstring(&b, "publickey"); + buffer_put_char(&b, have_sig); + buffer_put_cstring(&b, pkalg); + } + buffer_put_string(&b, pkblob, blen); #ifdef DEBUG_PK - buffer_dump(&b); + buffer_dump(&b); #endif - /* test for correct signature */ - authenticated = 0; - if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && - PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), - buffer_len(&b))) == 1) - authenticated = 1; - buffer_free(&b); - xfree(sig); - } else { - debug("test whether pkalg/pkblob are acceptable"); - packet_check_eom(); + /* test for correct signature */ + authenticated = 0; + if (PRIVSEP(user_key_allowed(authctxt->pw, key)) && + PRIVSEP(key_verify(key, sig, slen, buffer_ptr(&b), + buffer_len(&b))) == 1) + authenticated = 1; + buffer_free(&b); + xfree(sig); + } else { + debug("test whether pkalg/pkblob are acceptable"); + packet_check_eom(); - /* XXX fake reply and always send PK_OK ? */ - /* - * XXX this allows testing whether a user is allowed - * to login: if you happen to have a valid pubkey this - * message is sent. the message is NEVER sent at all - * if a user is not allowed to login. is this an - * issue? -markus - */ - if (PRIVSEP(user_key_allowed(authctxt->pw, key))) { - packet_start(SSH2_MSG_USERAUTH_PK_OK); - packet_put_string(pkalg, alen); - packet_put_string(pkblob, blen); - packet_send(); - packet_write_wait(); - authctxt->postponed = 1; - } - } - if (authenticated != 1) - auth_clear_options(); + /* XXX fake reply and always send PK_OK ? */ + /* + * XXX this allows testing whether a user is allowed + * to login: if you happen to have a valid pubkey this + * message is sent. the message is NEVER sent at all + * if a user is not allowed to login. is this an + * issue? -markus + */ + if (PRIVSEP(user_key_allowed(authctxt->pw, key))) { + packet_start(SSH2_MSG_USERAUTH_PK_OK); + packet_put_string(pkalg, alen); + packet_put_string(pkblob, blen); + packet_send(); + packet_write_wait(); + authctxt->postponed = 1; + } + } + if (authenticated != 1) + auth_clear_options(); done: - debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); - if (key != NULL) - key_free(key); - xfree(pkalg); - xfree(pkblob); - return authenticated; + debug2("userauth_pubkey: authenticated %d pkalg %s", authenticated, pkalg); + if (key != NULL) + key_free(key); + xfree(pkalg); + xfree(pkblob); + return authenticated; } /* return 1 if user allows given key */ static int user_key_allowed2(struct passwd *pw, Key *key, char *file) { - char line[SSH_MAX_PUBKEY_BYTES]; - int found_key = 0; - FILE *f; - u_long linenum = 0; - struct stat st; - Key *found; - char *fp; + char line[SSH_MAX_PUBKEY_BYTES]; + int found_key = 0; + FILE *f; + u_long linenum = 0; + struct stat st; + Key *found; + char *fp; - /* Temporarily use the user's uid. */ - temporarily_use_uid(pw); +#ifdef WITH_LDAP_PUBKEY + int i = 0; + lh_t host; + pkdata **data = NULL; +#endif - debug("trying public key file %s", file); + /* Temporarily use the user's uid. */ + temporarily_use_uid(pw); - /* Fail quietly if file does not exist */ - if (stat(file, &st) < 0) { - /* Restore the privileged uid. */ - restore_uid(); - return 0; - } - /* Open the file containing the authorized keys. */ - f = fopen(file, "r"); - if (!f) { - /* Restore the privileged uid. */ - restore_uid(); - return 0; - } - if (options.strict_modes && - secure_filename(f, file, pw, line, sizeof(line)) != 0) { - fclose(f); - logit("Authentication refused: %s", line); - restore_uid(); - return 0; - } +#ifdef WITH_LDAP_PUBKEY + found_key = 0; + /* allocate a new key type */ + found = key_new(key->type); - found_key = 0; - found = key_new(key->type); + /* first check if the options is enabled, then try.. */ + debug("trying LDAP first uid=%s",pw->pw_name); - while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { - char *cp, *key_options = NULL; + /* lets add it */ + host.lpkuurl = options.lpk_opt.lpk_user_server; + host.lpkufltr = options.lpk_opt.lpk_user_filter; + host.lpkgurl = options.lpk_opt.lpk_group_server; + host.lpkgfltr = options.lpk_opt.lpk_group_filter; + host.lpkbd = options.lpk_opt.lpk_binddn; + host.lpkbp = options.lpk_opt.lpk_bindpw; + host.lpksg = options.lpk_opt.lpk_srvgrp; - /* Skip leading whitespace, empty and comment lines. */ - for (cp = line; *cp == ' ' || *cp == '\t'; cp++) - ; - if (!*cp || *cp == '\n' || *cp == '#') - continue; + /* lets fill what we request */ - if (key_read(found, &cp) != 1) { - /* no key? check if there are options for this key */ - int quoted = 0; - debug2("user_key_allowed: check options: '%s'", cp); - key_options = cp; - for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if (*cp == '\\' && cp[1] == '"') - cp++; /* Skip both */ - else if (*cp == '"') - quoted = !quoted; - } - /* Skip remaining whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; - if (key_read(found, &cp) != 1) { - debug2("user_key_allowed: advance: '%s'", cp); - /* still no key? advance to next line*/ - continue; - } - } - if (key_equal(found, key) && - auth_parse_options(pw, key_options, file, linenum) == 1) { - found_key = 1; - debug("matching key found: file %s, line %lu", - file, linenum); - fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); - verbose("Found matching %s key: %s", - key_type(found), fp); - xfree(fp); - break; - } - } - restore_uid(); - fclose(f); - key_free(found); - if (!found_key) - debug2("key not found"); - return found_key; + if(options.lpk_opt.lpk_on && ( data = get_ldap_data(&host,pw) ) ) { + debug2("[LDAP] get_ldap_data() pubkey failed!!!"); + debug2("URL: %s !!",options.lpk_opt.lpk_user_server); + } + + if (data) + while (data[i] != NULL) { + char *cp, *options = NULL; + /* Skip leading whitespace, empty and comment lines. */ + for (cp = (char *)data[i++]->bv_val; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + + if (key_read(found, &cp) != 1) { + /* no key? check if there are options for this key */ + int quoted = 0; + debug2("[LDAP] user_key_allowed: check options: '%s'", cp); + options = cp; + for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { + if (*cp == '\\' && cp[1] == '"') + cp++; /* Skip both */ + else if (*cp == '"') + quoted = !quoted; + } + /* Skip remaining whitespace. */ + for (; *cp == ' ' || *cp == '\t'; cp++) + ; + if (key_read(found, &cp) != 1) { + debug2("[LDAP] user_key_allowed: advance: '%s'", cp); + /* still no key? advance to next line*/ + continue; + } + } + + if (key_equal(found, key) && + auth_parse_options(pw, options, file, linenum) == 1) { + found_key = 1; + debug("[LDAP] matching key found"); + fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + verbose("[LDAP] Found matching %s key: %s", + key_type(found), fp); + + /* restoring memory */ + ldap_value_free_len(data); + xfree(fp); + restore_uid(); + key_free(found); + return found_key; + break; + } + } + +#endif + + debug("trying public key file %s", file); + + /* Fail quietly if file does not exist */ + if (stat(file, &st) < 0) { + /* Restore the privileged uid. */ + restore_uid(); + return 0; + } + /* Open the file containing the authorized keys. */ + f = fopen(file, "r"); + if (!f) { + /* Restore the privileged uid. */ + restore_uid(); + return 0; + } + if (options.strict_modes && + secure_filename(f, file, pw, line, sizeof(line)) != 0) { + fclose(f); + logit("Authentication refused: %s", line); + restore_uid(); + return 0; + } + + found_key = 0; + found = key_new(key->type); + + while (read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { + char *cp, *key_options = NULL; + + /* Skip leading whitespace, empty and comment lines. */ + for (cp = line; *cp == ' ' || *cp == '\t'; cp++) + ; + if (!*cp || *cp == '\n' || *cp == '#') + continue; + + if (key_read(found, &cp) != 1) { + /* no key? check if there are options for this key */ + int quoted = 0; + debug2("user_key_allowed: check options: '%s'", cp); + key_options = cp; + for (; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { + if (*cp == '\\' && cp[1] == '"') + cp++; /* Skip both */ + else if (*cp == '"') + quoted = !quoted; + } + /* Skip remaining whitespace. */ + for (; *cp == ' ' || *cp == '\t'; cp++) + ; + if (key_read(found, &cp) != 1) { + debug2("user_key_allowed: advance: '%s'", cp); + /* still no key? advance to next line*/ + continue; + } + } + if (key_equal(found, key) && + auth_parse_options(pw, key_options, file, linenum) == 1) { + found_key = 1; + debug("matching key found: file %s, line %lu", + file, linenum); + fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s", + key_type(found), fp); + xfree(fp); + break; + } + } + restore_uid(); + fclose(f); + key_free(found); + if (!found_key) + debug2("key not found"); + return found_key; } /* check whether given key is in .ssh/authorized_keys* */ int user_key_allowed(struct passwd *pw, Key *key) { - int success; - char *file; + int success; + char *file; - file = authorized_keys_file(pw); - success = user_key_allowed2(pw, key, file); - xfree(file); - if (success) - return success; + file = authorized_keys_file(pw); + success = user_key_allowed2(pw, key, file); + xfree(file); + if (success) + return success; - /* try suffix "2" for backward compat, too */ - file = authorized_keys_file2(pw); - success = user_key_allowed2(pw, key, file); - xfree(file); - return success; + /* try suffix "2" for backward compat, too */ + file = authorized_keys_file2(pw); + success = user_key_allowed2(pw, key, file); + xfree(file); + return success; } Authmethod method_pubkey = { - "publickey", - userauth_pubkey, - &options.pubkey_authentication + "publickey", + userauth_pubkey, + &options.pubkey_authentication }; diff -ruN ssh.orig/key.c ssh/key.c --- ssh.orig/key.c Thu Mar 24 22:02:07 2005 +++ ssh/key.c Fri Mar 25 17:55:12 2005 @@ -36,6 +36,32 @@ #include +#ifdef WITH_LDAP_PUBKEY +/* + * defined in core.schema, this is a temporary objectclass which can be + * used since i m waiting for pkix schema and pubKey attribute (binary as well + * so minor changes for this patch), there will be an update about this ;) + * the following defs were for test purposes only + * i'm still keeping objectclass=strongAuthenticationuser because of the purpose + * this patch, and wrongly using cn for each user to store group includes + * refere to the README for a better understanding of this. + */ + +#include +#include + +#define PORT LDAP_PORT +#define LINEMAX 1024 + +/* just filter building stuff */ +#define REQUEST_GROUP(buffer,pwname,grp) \ +snprintf(buffer,LINEMAX,host->lpkgfltr,grp,pwname) + +#define REQUEST_USER(buffer,pwname) \ +snprintf(buffer,LINEMAX,host->lpkufltr,pwname); + +#endif + #include "xmalloc.h" #include "key.h" #include "rsa.h" @@ -47,277 +73,277 @@ Key * key_new(int type) { - Key *k; - RSA *rsa; - DSA *dsa; - k = xmalloc(sizeof(*k)); - k->type = type; - k->flags = 0; - k->dsa = NULL; - k->rsa = NULL; - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if ((rsa = RSA_new()) == NULL) - fatal("key_new: RSA_new failed"); - if ((rsa->n = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((rsa->e = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - k->rsa = rsa; - break; - case KEY_DSA: - if ((dsa = DSA_new()) == NULL) - fatal("key_new: DSA_new failed"); - if ((dsa->p = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->q = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->g = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - if ((dsa->pub_key = BN_new()) == NULL) - fatal("key_new: BN_new failed"); - k->dsa = dsa; - break; - case KEY_UNSPEC: - break; - default: - fatal("key_new: bad key type %d", k->type); - break; - } - return k; + Key *k; + RSA *rsa; + DSA *dsa; + k = xmalloc(sizeof(*k)); + k->type = type; + k->flags = 0; + k->dsa = NULL; + k->rsa = NULL; + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + if ((rsa = RSA_new()) == NULL) + fatal("key_new: RSA_new failed"); + if ((rsa->n = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((rsa->e = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + k->rsa = rsa; + break; + case KEY_DSA: + if ((dsa = DSA_new()) == NULL) + fatal("key_new: DSA_new failed"); + if ((dsa->p = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->q = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->g = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + if ((dsa->pub_key = BN_new()) == NULL) + fatal("key_new: BN_new failed"); + k->dsa = dsa; + break; + case KEY_UNSPEC: + break; + default: + fatal("key_new: bad key type %d", k->type); + break; + } + return k; } Key * key_new_private(int type) { - Key *k = key_new(type); - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if ((k->rsa->d = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->iqmp = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->q = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->p = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->dmq1 = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - if ((k->rsa->dmp1 = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - break; - case KEY_DSA: - if ((k->dsa->priv_key = BN_new()) == NULL) - fatal("key_new_private: BN_new failed"); - break; - case KEY_UNSPEC: - break; - default: - break; - } - return k; + Key *k = key_new(type); + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + if ((k->rsa->d = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->iqmp = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->q = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->p = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->dmq1 = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + if ((k->rsa->dmp1 = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + break; + case KEY_DSA: + if ((k->dsa->priv_key = BN_new()) == NULL) + fatal("key_new_private: BN_new failed"); + break; + case KEY_UNSPEC: + break; + default: + break; + } + return k; } void key_free(Key *k) { - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if (k->rsa != NULL) - RSA_free(k->rsa); - k->rsa = NULL; - break; - case KEY_DSA: - if (k->dsa != NULL) - DSA_free(k->dsa); - k->dsa = NULL; - break; - case KEY_UNSPEC: - break; - default: - fatal("key_free: bad key type %d", k->type); - break; - } - xfree(k); + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + if (k->rsa != NULL) + RSA_free(k->rsa); + k->rsa = NULL; + break; + case KEY_DSA: + if (k->dsa != NULL) + DSA_free(k->dsa); + k->dsa = NULL; + break; + case KEY_UNSPEC: + break; + default: + fatal("key_free: bad key type %d", k->type); + break; + } + xfree(k); } int key_equal(const Key *a, const Key *b) { - if (a == NULL || b == NULL || a->type != b->type) - return 0; - switch (a->type) { - case KEY_RSA1: - case KEY_RSA: - return a->rsa != NULL && b->rsa != NULL && - BN_cmp(a->rsa->e, b->rsa->e) == 0 && - BN_cmp(a->rsa->n, b->rsa->n) == 0; - break; - case KEY_DSA: - return a->dsa != NULL && b->dsa != NULL && - BN_cmp(a->dsa->p, b->dsa->p) == 0 && - BN_cmp(a->dsa->q, b->dsa->q) == 0 && - BN_cmp(a->dsa->g, b->dsa->g) == 0 && - BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; - break; - default: - fatal("key_equal: bad key type %d", a->type); - break; - } - return 0; + if (a == NULL || b == NULL || a->type != b->type) + return 0; + switch (a->type) { + case KEY_RSA1: + case KEY_RSA: + return a->rsa != NULL && b->rsa != NULL && + BN_cmp(a->rsa->e, b->rsa->e) == 0 && + BN_cmp(a->rsa->n, b->rsa->n) == 0; + break; + case KEY_DSA: + return a->dsa != NULL && b->dsa != NULL && + BN_cmp(a->dsa->p, b->dsa->p) == 0 && + BN_cmp(a->dsa->q, b->dsa->q) == 0 && + BN_cmp(a->dsa->g, b->dsa->g) == 0 && + BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; + break; + default: + fatal("key_equal: bad key type %d", a->type); + break; + } + return 0; } u_char* key_fingerprint_raw(const Key *k, enum fp_type dgst_type, u_int *dgst_raw_length) { - const EVP_MD *md = NULL; - EVP_MD_CTX ctx; - u_char *blob = NULL; - u_char *retval = NULL; - u_int len = 0; - int nlen, elen; + const EVP_MD *md = NULL; + EVP_MD_CTX ctx; + u_char *blob = NULL; + u_char *retval = NULL; + u_int len = 0; + int nlen, elen; - *dgst_raw_length = 0; + *dgst_raw_length = 0; - switch (dgst_type) { - case SSH_FP_MD5: - md = EVP_md5(); - break; - case SSH_FP_SHA1: - md = EVP_sha1(); - break; - default: - fatal("key_fingerprint_raw: bad digest type %d", - dgst_type); - } - switch (k->type) { - case KEY_RSA1: - nlen = BN_num_bytes(k->rsa->n); - elen = BN_num_bytes(k->rsa->e); - len = nlen + elen; - blob = xmalloc(len); - BN_bn2bin(k->rsa->n, blob); - BN_bn2bin(k->rsa->e, blob + nlen); - break; - case KEY_DSA: - case KEY_RSA: - key_to_blob(k, &blob, &len); - break; - case KEY_UNSPEC: - return retval; - break; - default: - fatal("key_fingerprint_raw: bad key type %d", k->type); - break; - } - if (blob != NULL) { - retval = xmalloc(EVP_MAX_MD_SIZE); - EVP_DigestInit(&ctx, md); - EVP_DigestUpdate(&ctx, blob, len); - EVP_DigestFinal(&ctx, retval, dgst_raw_length); - memset(blob, 0, len); - xfree(blob); - } else { - fatal("key_fingerprint_raw: blob is null"); - } - return retval; + switch (dgst_type) { + case SSH_FP_MD5: + md = EVP_md5(); + break; + case SSH_FP_SHA1: + md = EVP_sha1(); + break; + default: + fatal("key_fingerprint_raw: bad digest type %d", + dgst_type); + } + switch (k->type) { + case KEY_RSA1: + nlen = BN_num_bytes(k->rsa->n); + elen = BN_num_bytes(k->rsa->e); + len = nlen + elen; + blob = xmalloc(len); + BN_bn2bin(k->rsa->n, blob); + BN_bn2bin(k->rsa->e, blob + nlen); + break; + case KEY_DSA: + case KEY_RSA: + key_to_blob(k, &blob, &len); + break; + case KEY_UNSPEC: + return retval; + break; + default: + fatal("key_fingerprint_raw: bad key type %d", k->type); + break; + } + if (blob != NULL) { + retval = xmalloc(EVP_MAX_MD_SIZE); + EVP_DigestInit(&ctx, md); + EVP_DigestUpdate(&ctx, blob, len); + EVP_DigestFinal(&ctx, retval, dgst_raw_length); + memset(blob, 0, len); + xfree(blob); + } else { + fatal("key_fingerprint_raw: blob is null"); + } + return retval; } static char * key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len) { - char *retval; - int i; + char *retval; + int i; - retval = xmalloc(dgst_raw_len * 3 + 1); - retval[0] = '\0'; - for (i = 0; i < dgst_raw_len; i++) { - char hex[4]; - snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); - strlcat(retval, hex, dgst_raw_len * 3 + 1); - } + retval = xmalloc(dgst_raw_len * 3 + 1); + retval[0] = '\0'; + for (i = 0; i < dgst_raw_len; i++) { + char hex[4]; + snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]); + strlcat(retval, hex, dgst_raw_len * 3 + 1); + } - /* Remove the trailing ':' character */ - retval[(dgst_raw_len * 3) - 1] = '\0'; - return retval; + /* Remove the trailing ':' character */ + retval[(dgst_raw_len * 3) - 1] = '\0'; + return retval; } static char * key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len) { - char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; - char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', - 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; - u_int i, j = 0, rounds, seed = 1; - char *retval; + char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' }; + char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm', + 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' }; + u_int i, j = 0, rounds, seed = 1; + char *retval; - rounds = (dgst_raw_len / 2) + 1; - retval = xmalloc(sizeof(char) * (rounds*6)); - retval[j++] = 'x'; - for (i = 0; i < rounds; i++) { - u_int idx0, idx1, idx2, idx3, idx4; - if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { - idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + - seed) % 6; - idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; - idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + - (seed / 6)) % 6; - retval[j++] = vowels[idx0]; - retval[j++] = consonants[idx1]; - retval[j++] = vowels[idx2]; - if ((i + 1) < rounds) { - idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; - idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; - retval[j++] = consonants[idx3]; - retval[j++] = '-'; - retval[j++] = consonants[idx4]; - seed = ((seed * 5) + - ((((u_int)(dgst_raw[2 * i])) * 7) + - ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; - } - } else { - idx0 = seed % 6; - idx1 = 16; - idx2 = seed / 6; - retval[j++] = vowels[idx0]; - retval[j++] = consonants[idx1]; - retval[j++] = vowels[idx2]; - } - } - retval[j++] = 'x'; - retval[j++] = '\0'; - return retval; + rounds = (dgst_raw_len / 2) + 1; + retval = xmalloc(sizeof(char) * (rounds*6)); + retval[j++] = 'x'; + for (i = 0; i < rounds; i++) { + u_int idx0, idx1, idx2, idx3, idx4; + if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) { + idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) + + seed) % 6; + idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15; + idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) + + (seed / 6)) % 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + if ((i + 1) < rounds) { + idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15; + idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15; + retval[j++] = consonants[idx3]; + retval[j++] = '-'; + retval[j++] = consonants[idx4]; + seed = ((seed * 5) + + ((((u_int)(dgst_raw[2 * i])) * 7) + + ((u_int)(dgst_raw[(2 * i) + 1])))) % 36; + } + } else { + idx0 = seed % 6; + idx1 = 16; + idx2 = seed / 6; + retval[j++] = vowels[idx0]; + retval[j++] = consonants[idx1]; + retval[j++] = vowels[idx2]; + } + } + retval[j++] = 'x'; + retval[j++] = '\0'; + return retval; } char * key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep) { - char *retval = NULL; - u_char *dgst_raw; - u_int dgst_raw_len; + char *retval = NULL; + u_char *dgst_raw; + u_int dgst_raw_len; - dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); - if (!dgst_raw) - fatal("key_fingerprint: null from key_fingerprint_raw()"); - switch (dgst_rep) { - case SSH_FP_HEX: - retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); - break; - case SSH_FP_BUBBLEBABBLE: - retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); - break; - default: - fatal("key_fingerprint_ex: bad digest representation %d", - dgst_rep); - break; - } - memset(dgst_raw, 0, dgst_raw_len); - xfree(dgst_raw); - return retval; + dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len); + if (!dgst_raw) + fatal("key_fingerprint: null from key_fingerprint_raw()"); + switch (dgst_rep) { + case SSH_FP_HEX: + retval = key_fingerprint_hex(dgst_raw, dgst_raw_len); + break; + case SSH_FP_BUBBLEBABBLE: + retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len); + break; + default: + fatal("key_fingerprint_ex: bad digest representation %d", + dgst_rep); + break; + } + memset(dgst_raw, 0, dgst_raw_len); + xfree(dgst_raw); + return retval; } /* @@ -330,458 +356,588 @@ static int read_bignum(char **cpp, BIGNUM * value) { - char *cp = *cpp; - int old; + char *cp = *cpp; + int old; - /* Skip any leading whitespace. */ - for (; *cp == ' ' || *cp == '\t'; cp++) - ; + /* Skip any leading whitespace. */ + for (; *cp == ' ' || *cp == '\t'; cp++) + ; - /* Check that it begins with a decimal digit. */ - if (*cp < '0' || *cp > '9') - return 0; + /* Check that it begins with a decimal digit. */ + if (*cp < '0' || *cp > '9') + return 0; - /* Save starting position. */ - *cpp = cp; + /* Save starting position. */ + *cpp = cp; - /* Move forward until all decimal digits skipped. */ - for (; *cp >= '0' && *cp <= '9'; cp++) - ; + /* Move forward until all decimal digits skipped. */ + for (; *cp >= '0' && *cp <= '9'; cp++) + ; - /* Save the old terminating character, and replace it by \0. */ - old = *cp; - *cp = 0; + /* Save the old terminating character, and replace it by \0. */ + old = *cp; + *cp = 0; - /* Parse the number. */ - if (BN_dec2bn(&value, *cpp) == 0) - return 0; + /* Parse the number. */ + if (BN_dec2bn(&value, *cpp) == 0) + return 0; - /* Restore old terminating character. */ - *cp = old; + /* Restore old terminating character. */ + *cp = old; - /* Move beyond the number and return success. */ - *cpp = cp; - return 1; + /* Move beyond the number and return success. */ + *cpp = cp; + return 1; } static int write_bignum(FILE *f, BIGNUM *num) { - char *buf = BN_bn2dec(num); - if (buf == NULL) { - error("write_bignum: BN_bn2dec() failed"); - return 0; - } - fprintf(f, " %s", buf); - OPENSSL_free(buf); - return 1; + char *buf = BN_bn2dec(num); + if (buf == NULL) { + error("write_bignum: BN_bn2dec() failed"); + return 0; + } + fprintf(f, " %s", buf); + OPENSSL_free(buf); + return 1; } +#ifdef WITH_LDAP_PUBKEY + +/* get data needed for certificate and group management */ +pkdata ** get_ldap_data(lh_t *host, struct passwd *pw) { + LDAP *ld; + LDAPMessage *res, *e; + LDAPURLDesc *usr_urlstruct, *grp_urlstruct; + BerElement *ptr; + struct berval **vals; + int version, rc, i; + char *a,objbuf[LINEMAX]; + + /* version to 3 */ + version = LDAP_VERSION3; + + debug2("[LDAP] get_ldap_data()"); + + /* url based ldap://hostport/dn[?attrs[?scope[?filter[?exts]]]] */ + rc = ldap_is_ldap_url(host->lpkuurl); + if (rc < 0) { + error("get_ldap_data: ldap_is_ldap_url(UserUrl) -> ldap is not a url"); + return NULL; + } + /* parse the User URL format */ + rc = ldap_url_parse(host->lpkuurl,&usr_urlstruct); + if (rc) { + error("get_ldap_data: ldap_url_parse(UserUrl) -> ldap couldn't be parsed"); + return NULL; + } + + debug3("[LDAP] ldap url parsed"); + + /* open ldap connection */ + ld = ldap_init(usr_urlstruct->lud_host,usr_urlstruct->lud_port); + if(!ld) { + error("get_ldap_data: ldap_init()"); + /* free what has been allocated */ + ldap_free_urldesc(usr_urlstruct); + return NULL; + } + + /* setting V3 proto */ + if (ldap_set_option(ld,LDAP_OPT_PROTOCOL_VERSION,&version) != LDAP_OPT_SUCCESS) { + error("get_ldap_data: ldap couldn't set version "); + /* free what has been allocated */ + ldap_free_urldesc(usr_urlstruct); + return NULL; + } + + /* anonymous bind pubkey can be retrieved by anybody */ + if (ldap_simple_bind_s(ld,host->lpkbd,host->lpkbp) != LDAP_SUCCESS) { + error("get_ldap_data: ldap_simple_bind_s()"); + + /* free what has been allocated */ + ldap_free_urldesc(usr_urlstruct); + return NULL; + } + + /* New filter group inclusive depend on the configuration */ + /* (&(objectclass=posixGroup)(&(cn=unix)(memberUid=eau))) */ + debug("[LDAP] group y/n?"); + if (host->lpksg && host->lpkgurl) { + debug2("[LDAP-group] '%s' part of group '%s'",pw->pw_name ,host->lpksg); + + /* url based ldap://hostport/dn[?attrs[?scope[?filter[?exts]]]] */ + rc = ldap_is_ldap_url(host->lpkgurl); + if (rc < 0) { + error("get_ldap_data: ldap_is_ldap_url(GroupUrl) -> ldap is not a url"); + ldap_free_urldesc(usr_urlstruct); + return NULL; + } + /* parse the Group URL format */ + rc = ldap_url_parse(host->lpkgurl,&grp_urlstruct); + if (rc) { + error("get_ldap_data: ldap_url_parse(GroupUrl) -> ldap couldn't be parsed"); + ldap_free_urldesc(usr_urlstruct); + return NULL; + } + /*snprintf(objbuf,LINEMAX,"(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))",request->pk_group,request->pk_pw->pw_name);*/ + + + REQUEST_GROUP(objbuf,pw->pw_name,host->lpksg); + + ldap_search_s(ld,grp_urlstruct->lud_dn,LDAP_SCOPE_SUBTREE,objbuf,NULL,0,&res); + i = ldap_count_entries(ld,res); + debug2("[LDAP-group] results: %d",i); + if (i <= 0) { + debug2("[LDAP-group] uid: %s not in '%s'",pw->pw_name, host->lpksg); + error("get_ldap_data: '%s' is not in '%s'", pw->pw_name, host->lpksg); + ldap_free_urldesc(usr_urlstruct); + ldap_free_urldesc(grp_urlstruct); + return NULL; + } + ldap_free_urldesc(grp_urlstruct); + } + + /* cleaning memory slots */ + memset(objbuf,0,LINEMAX); + + /* user request */ + /* (&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(&(cn=*groupname*)(uid=eau))) */ + /* snprintf(objbuf,LINEMAX,"(&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(uid=%s))",request->pk_pw->pw_name); + * */ + + debug2("[LDAP] searching '%s''s keys", pw->pw_name); + REQUEST_USER(objbuf,pw->pw_name); + + ldap_search_s(ld,usr_urlstruct->lud_dn,LDAP_SCOPE_SUBTREE,objbuf,NULL,0,&res); + i = ldap_count_entries(ld,res); + + if (i > 0) + for(e=ldap_first_entry(ld,res); e != NULL; e=ldap_next_entry(ld,e)) { + ldap_get_dn(ld,e); + for(a=ldap_first_attribute(ld,e,&ptr);a!=NULL;a=ldap_next_attribute(ld,e,ptr)) { + if(strncmp(a,"userCertificate",15) == 0) { + debug2("[LDAP] found some keys returning"); + vals=ldap_get_values_len(ld,e,a); + ldap_free_urldesc(usr_urlstruct); + ldap_unbind_s(ld); + return vals; + } /* end of if(strncmp) */ + } /* end of for */ + } /* end of for */ + + ldap_free_urldesc(usr_urlstruct); + ldap_unbind_s(ld); + + return NULL; +} +#endif + /* returns 1 ok, -1 error */ int key_read(Key *ret, char **cpp) { - Key *k; - int success = -1; - char *cp, *space; - int len, n, type; - u_int bits; - u_char *blob; + Key *k; + int success = -1; + char *cp, *space; + int len, n, type; + u_int bits; + u_char *blob; - cp = *cpp; + cp = *cpp; - switch (ret->type) { - case KEY_RSA1: - /* Get number of bits. */ - if (*cp < '0' || *cp > '9') - return -1; /* Bad bit count... */ - for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) - bits = 10 * bits + *cp - '0'; - if (bits == 0) - return -1; - *cpp = cp; - /* Get public exponent, public modulus. */ - if (!read_bignum(cpp, ret->rsa->e)) - return -1; - if (!read_bignum(cpp, ret->rsa->n)) - return -1; - success = 1; - break; - case KEY_UNSPEC: - case KEY_RSA: - case KEY_DSA: - space = strchr(cp, ' '); - if (space == NULL) { - debug3("key_read: missing whitespace"); - return -1; - } - *space = '\0'; - type = key_type_from_name(cp); - *space = ' '; - if (type == KEY_UNSPEC) { - debug3("key_read: missing keytype"); - return -1; - } - cp = space+1; - if (*cp == '\0') { - debug3("key_read: short string"); - return -1; - } - if (ret->type == KEY_UNSPEC) { - ret->type = type; - } else if (ret->type != type) { - /* is a key, but different type */ - debug3("key_read: type mismatch"); - return -1; - } - len = 2*strlen(cp); - blob = xmalloc(len); - n = uudecode(cp, blob, len); - if (n < 0) { - error("key_read: uudecode %s failed", cp); - xfree(blob); - return -1; - } - k = key_from_blob(blob, (u_int)n); - xfree(blob); - if (k == NULL) { - error("key_read: key_from_blob %s failed", cp); - return -1; - } - if (k->type != type) { - error("key_read: type mismatch: encoding error"); - key_free(k); - return -1; - } + switch (ret->type) { + case KEY_RSA1: + /* Get number of bits. */ + if (*cp < '0' || *cp > '9') + return -1; /* Bad bit count... */ + for (bits = 0; *cp >= '0' && *cp <= '9'; cp++) + bits = 10 * bits + *cp - '0'; + if (bits == 0) + return -1; + *cpp = cp; + /* Get public exponent, public modulus. */ + if (!read_bignum(cpp, ret->rsa->e)) + return -1; + if (!read_bignum(cpp, ret->rsa->n)) + return -1; + success = 1; + break; + case KEY_UNSPEC: + case KEY_RSA: + case KEY_DSA: + space = strchr(cp, ' '); + if (space == NULL) { + debug3("key_read: missing whitespace"); + return -1; + } + *space = '\0'; + type = key_type_from_name(cp); + *space = ' '; + if (type == KEY_UNSPEC) { + debug3("key_read: missing keytype"); + return -1; + } + cp = space+1; + if (*cp == '\0') { + debug3("key_read: short string"); + return -1; + } + if (ret->type == KEY_UNSPEC) { + ret->type = type; + } else if (ret->type != type) { + /* is a key, but different type */ + debug3("key_read: type mismatch"); + return -1; + } + len = 2*strlen(cp); + blob = xmalloc(len); + n = uudecode(cp, blob, len); + if (n < 0) { + error("key_read: uudecode %s failed", cp); + xfree(blob); + return -1; + } + k = key_from_blob(blob, (u_int)n); + xfree(blob); + if (k == NULL) { + error("key_read: key_from_blob %s failed", cp); + return -1; + } + if (k->type != type) { + error("key_read: type mismatch: encoding error"); + key_free(k); + return -1; + } /*XXXX*/ - if (ret->type == KEY_RSA) { - if (ret->rsa != NULL) - RSA_free(ret->rsa); - ret->rsa = k->rsa; - k->rsa = NULL; - success = 1; + if (ret->type == KEY_RSA) { + if (ret->rsa != NULL) + RSA_free(ret->rsa); + ret->rsa = k->rsa; + k->rsa = NULL; + success = 1; #ifdef DEBUG_PK - RSA_print_fp(stderr, ret->rsa, 8); + RSA_print_fp(stderr, ret->rsa, 8); #endif - } else { - if (ret->dsa != NULL) - DSA_free(ret->dsa); - ret->dsa = k->dsa; - k->dsa = NULL; - success = 1; + } else { + if (ret->dsa != NULL) + DSA_free(ret->dsa); + ret->dsa = k->dsa; + k->dsa = NULL; + success = 1; #ifdef DEBUG_PK - DSA_print_fp(stderr, ret->dsa, 8); + DSA_print_fp(stderr, ret->dsa, 8); #endif - } + } /*XXXX*/ - key_free(k); - if (success != 1) - break; - /* advance cp: skip whitespace and data */ - while (*cp == ' ' || *cp == '\t') - cp++; - while (*cp != '\0' && *cp != ' ' && *cp != '\t') - cp++; - *cpp = cp; - break; - default: - fatal("key_read: bad key type: %d", ret->type); - break; - } - return success; + key_free(k); + if (success != 1) + break; + /* advance cp: skip whitespace and data */ + while (*cp == ' ' || *cp == '\t') + cp++; + while (*cp != '\0' && *cp != ' ' && *cp != '\t') + cp++; + *cpp = cp; + break; + default: + fatal("key_read: bad key type: %d", ret->type); + break; + } + return success; } int key_write(const Key *key, FILE *f) { - int n, success = 0; - u_int len, bits = 0; - u_char *blob; - char *uu; + int n, success = 0; + u_int len, bits = 0; + u_char *blob; + char *uu; - if (key->type == KEY_RSA1 && key->rsa != NULL) { - /* size of modulus 'n' */ - bits = BN_num_bits(key->rsa->n); - fprintf(f, "%u", bits); - if (write_bignum(f, key->rsa->e) && - write_bignum(f, key->rsa->n)) { - success = 1; - } else { - error("key_write: failed for RSA key"); - } - } else if ((key->type == KEY_DSA && key->dsa != NULL) || - (key->type == KEY_RSA && key->rsa != NULL)) { - key_to_blob(key, &blob, &len); - uu = xmalloc(2*len); - n = uuencode(blob, len, uu, 2*len); - if (n > 0) { - fprintf(f, "%s %s", key_ssh_name(key), uu); - success = 1; - } - xfree(blob); - xfree(uu); - } - return success; + if (key->type == KEY_RSA1 && key->rsa != NULL) { + /* size of modulus 'n' */ + bits = BN_num_bits(key->rsa->n); + fprintf(f, "%u", bits); + if (write_bignum(f, key->rsa->e) && + write_bignum(f, key->rsa->n)) { + success = 1; + } else { + error("key_write: failed for RSA key"); + } + } else if ((key->type == KEY_DSA && key->dsa != NULL) || + (key->type == KEY_RSA && key->rsa != NULL)) { + key_to_blob(key, &blob, &len); + uu = xmalloc(2*len); + n = uuencode(blob, len, uu, 2*len); + if (n > 0) { + fprintf(f, "%s %s", key_ssh_name(key), uu); + success = 1; + } + xfree(blob); + xfree(uu); + } + return success; } const char * key_type(const Key *k) { - switch (k->type) { - case KEY_RSA1: - return "RSA1"; - break; - case KEY_RSA: - return "RSA"; - break; - case KEY_DSA: - return "DSA"; - break; - } - return "unknown"; + switch (k->type) { + case KEY_RSA1: + return "RSA1"; + break; + case KEY_RSA: + return "RSA"; + break; + case KEY_DSA: + return "DSA"; + break; + } + return "unknown"; } const char * key_ssh_name(const Key *k) { - switch (k->type) { - case KEY_RSA: - return "ssh-rsa"; - break; - case KEY_DSA: - return "ssh-dss"; - break; - } - return "ssh-unknown"; + switch (k->type) { + case KEY_RSA: + return "ssh-rsa"; + break; + case KEY_DSA: + return "ssh-dss"; + break; + } + return "ssh-unknown"; } u_int key_size(const Key *k) { - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - return BN_num_bits(k->rsa->n); - break; - case KEY_DSA: - return BN_num_bits(k->dsa->p); - break; - } - return 0; + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + return BN_num_bits(k->rsa->n); + break; + case KEY_DSA: + return BN_num_bits(k->dsa->p); + break; + } + return 0; } static RSA * rsa_generate_private_key(u_int bits) { - RSA *private; - private = RSA_generate_key(bits, 35, NULL, NULL); - if (private == NULL) - fatal("rsa_generate_private_key: key generation failed."); - return private; + RSA *private; + private = RSA_generate_key(bits, 35, NULL, NULL); + if (private == NULL) + fatal("rsa_generate_private_key: key generation failed."); + return private; } static DSA* dsa_generate_private_key(u_int bits) { - DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); - if (private == NULL) - fatal("dsa_generate_private_key: DSA_generate_parameters failed"); - if (!DSA_generate_key(private)) - fatal("dsa_generate_private_key: DSA_generate_key failed."); - if (private == NULL) - fatal("dsa_generate_private_key: NULL."); - return private; + DSA *private = DSA_generate_parameters(bits, NULL, 0, NULL, NULL, NULL, NULL); + if (private == NULL) + fatal("dsa_generate_private_key: DSA_generate_parameters failed"); + if (!DSA_generate_key(private)) + fatal("dsa_generate_private_key: DSA_generate_key failed."); + if (private == NULL) + fatal("dsa_generate_private_key: NULL."); + return private; } Key * key_generate(int type, u_int bits) { - Key *k = key_new(KEY_UNSPEC); - switch (type) { - case KEY_DSA: - k->dsa = dsa_generate_private_key(bits); - break; - case KEY_RSA: - case KEY_RSA1: - k->rsa = rsa_generate_private_key(bits); - break; - default: - fatal("key_generate: unknown type %d", type); - } - k->type = type; - return k; + Key *k = key_new(KEY_UNSPEC); + switch (type) { + case KEY_DSA: + k->dsa = dsa_generate_private_key(bits); + break; + case KEY_RSA: + case KEY_RSA1: + k->rsa = rsa_generate_private_key(bits); + break; + default: + fatal("key_generate: unknown type %d", type); + } + k->type = type; + return k; } Key * key_from_private(const Key *k) { - Key *n = NULL; - switch (k->type) { - case KEY_DSA: - n = key_new(k->type); - BN_copy(n->dsa->p, k->dsa->p); - BN_copy(n->dsa->q, k->dsa->q); - BN_copy(n->dsa->g, k->dsa->g); - BN_copy(n->dsa->pub_key, k->dsa->pub_key); - break; - case KEY_RSA: - case KEY_RSA1: - n = key_new(k->type); - BN_copy(n->rsa->n, k->rsa->n); - BN_copy(n->rsa->e, k->rsa->e); - break; - default: - fatal("key_from_private: unknown type %d", k->type); - break; - } - return n; + Key *n = NULL; + switch (k->type) { + case KEY_DSA: + n = key_new(k->type); + BN_copy(n->dsa->p, k->dsa->p); + BN_copy(n->dsa->q, k->dsa->q); + BN_copy(n->dsa->g, k->dsa->g); + BN_copy(n->dsa->pub_key, k->dsa->pub_key); + break; + case KEY_RSA: + case KEY_RSA1: + n = key_new(k->type); + BN_copy(n->rsa->n, k->rsa->n); + BN_copy(n->rsa->e, k->rsa->e); + break; + default: + fatal("key_from_private: unknown type %d", k->type); + break; + } + return n; } int key_type_from_name(char *name) { - if (strcmp(name, "rsa1") == 0) { - return KEY_RSA1; - } else if (strcmp(name, "rsa") == 0) { - return KEY_RSA; - } else if (strcmp(name, "dsa") == 0) { - return KEY_DSA; - } else if (strcmp(name, "ssh-rsa") == 0) { - return KEY_RSA; - } else if (strcmp(name, "ssh-dss") == 0) { - return KEY_DSA; - } - debug2("key_type_from_name: unknown key type '%s'", name); - return KEY_UNSPEC; + if (strcmp(name, "rsa1") == 0) { + return KEY_RSA1; + } else if (strcmp(name, "rsa") == 0) { + return KEY_RSA; + } else if (strcmp(name, "dsa") == 0) { + return KEY_DSA; + } else if (strcmp(name, "ssh-rsa") == 0) { + return KEY_RSA; + } else if (strcmp(name, "ssh-dss") == 0) { + return KEY_DSA; + } + debug2("key_type_from_name: unknown key type '%s'", name); + return KEY_UNSPEC; } int key_names_valid2(const char *names) { - char *s, *cp, *p; + char *s, *cp, *p; - if (names == NULL || strcmp(names, "") == 0) - return 0; - s = cp = xstrdup(names); - for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { - switch (key_type_from_name(p)) { - case KEY_RSA1: - case KEY_UNSPEC: - xfree(s); - return 0; - } - } - debug3("key names ok: [%s]", names); - xfree(s); - return 1; + if (names == NULL || strcmp(names, "") == 0) + return 0; + s = cp = xstrdup(names); + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + switch (key_type_from_name(p)) { + case KEY_RSA1: + case KEY_UNSPEC: + xfree(s); + return 0; + } + } + debug3("key names ok: [%s]", names); + xfree(s); + return 1; } Key * key_from_blob(const u_char *blob, u_int blen) { - Buffer b; - int rlen, type; - char *ktype = NULL; - Key *key = NULL; + Buffer b; + int rlen, type; + char *ktype = NULL; + Key *key = NULL; #ifdef DEBUG_PK - dump_base64(stderr, blob, blen); + dump_base64(stderr, blob, blen); #endif - buffer_init(&b); - buffer_append(&b, blob, blen); - if ((ktype = buffer_get_string_ret(&b, NULL)) == NULL) { - error("key_from_blob: can't read key type"); - goto out; - } + buffer_init(&b); + buffer_append(&b, blob, blen); + if ((ktype = buffer_get_string_ret(&b, NULL)) == NULL) { + error("key_from_blob: can't read key type"); + goto out; + } - type = key_type_from_name(ktype); + type = key_type_from_name(ktype); - switch (type) { - case KEY_RSA: - key = key_new(type); - if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || - buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { - error("key_from_blob: can't read rsa key"); - key_free(key); - key = NULL; - goto out; - } + switch (type) { + case KEY_RSA: + key = key_new(type); + if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 || + buffer_get_bignum2_ret(&b, key->rsa->n) == -1) { + error("key_from_blob: can't read rsa key"); + key_free(key); + key = NULL; + goto out; + } #ifdef DEBUG_PK - RSA_print_fp(stderr, key->rsa, 8); + RSA_print_fp(stderr, key->rsa, 8); #endif - break; - case KEY_DSA: - key = key_new(type); - if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || - buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { - error("key_from_blob: can't read dsa key"); - key_free(key); - key = NULL; - goto out; - } + break; + case KEY_DSA: + key = key_new(type); + if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 || + buffer_get_bignum2_ret(&b, key->dsa->q) == -1 || + buffer_get_bignum2_ret(&b, key->dsa->g) == -1 || + buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) { + error("key_from_blob: can't read dsa key"); + key_free(key); + key = NULL; + goto out; + } #ifdef DEBUG_PK - DSA_print_fp(stderr, key->dsa, 8); + DSA_print_fp(stderr, key->dsa, 8); #endif - break; - case KEY_UNSPEC: - key = key_new(type); - break; - default: - error("key_from_blob: cannot handle type %s", ktype); - goto out; - } - rlen = buffer_len(&b); - if (key != NULL && rlen != 0) - error("key_from_blob: remaining bytes in key blob %d", rlen); + break; + case KEY_UNSPEC: + key = key_new(type); + break; + default: + error("key_from_blob: cannot handle type %s", ktype); + goto out; + } + rlen = buffer_len(&b); + if (key != NULL && rlen != 0) + error("key_from_blob: remaining bytes in key blob %d", rlen); out: - if (ktype != NULL) - xfree(ktype); - buffer_free(&b); - return key; + if (ktype != NULL) + xfree(ktype); + buffer_free(&b); + return key; } int key_to_blob(const Key *key, u_char **blobp, u_int *lenp) { - Buffer b; - int len; + Buffer b; + int len; - if (key == NULL) { - error("key_to_blob: key == NULL"); - return 0; - } - buffer_init(&b); - switch (key->type) { - case KEY_DSA: - buffer_put_cstring(&b, key_ssh_name(key)); - buffer_put_bignum2(&b, key->dsa->p); - buffer_put_bignum2(&b, key->dsa->q); - buffer_put_bignum2(&b, key->dsa->g); - buffer_put_bignum2(&b, key->dsa->pub_key); - break; - case KEY_RSA: - buffer_put_cstring(&b, key_ssh_name(key)); - buffer_put_bignum2(&b, key->rsa->e); - buffer_put_bignum2(&b, key->rsa->n); - break; - default: - error("key_to_blob: unsupported key type %d", key->type); - buffer_free(&b); - return 0; - } - len = buffer_len(&b); - if (lenp != NULL) - *lenp = len; - if (blobp != NULL) { - *blobp = xmalloc(len); - memcpy(*blobp, buffer_ptr(&b), len); - } - memset(buffer_ptr(&b), 0, len); - buffer_free(&b); - return len; + if (key == NULL) { + error("key_to_blob: key == NULL"); + return 0; + } + buffer_init(&b); + switch (key->type) { + case KEY_DSA: + buffer_put_cstring(&b, key_ssh_name(key)); + buffer_put_bignum2(&b, key->dsa->p); + buffer_put_bignum2(&b, key->dsa->q); + buffer_put_bignum2(&b, key->dsa->g); + buffer_put_bignum2(&b, key->dsa->pub_key); + break; + case KEY_RSA: + buffer_put_cstring(&b, key_ssh_name(key)); + buffer_put_bignum2(&b, key->rsa->e); + buffer_put_bignum2(&b, key->rsa->n); + break; + default: + error("key_to_blob: unsupported key type %d", key->type); + buffer_free(&b); + return 0; + } + len = buffer_len(&b); + if (lenp != NULL) + *lenp = len; + if (blobp != NULL) { + *blobp = xmalloc(len); + memcpy(*blobp, buffer_ptr(&b), len); + } + memset(buffer_ptr(&b), 0, len); + buffer_free(&b); + return len; } int @@ -790,18 +946,18 @@ u_char **sigp, u_int *lenp, const u_char *data, u_int datalen) { - switch (key->type) { - case KEY_DSA: - return ssh_dss_sign(key, sigp, lenp, data, datalen); - break; - case KEY_RSA: - return ssh_rsa_sign(key, sigp, lenp, data, datalen); - break; - default: - error("key_sign: invalid key type %d", key->type); - return -1; - break; - } + switch (key->type) { + case KEY_DSA: + return ssh_dss_sign(key, sigp, lenp, data, datalen); + break; + case KEY_RSA: + return ssh_rsa_sign(key, sigp, lenp, data, datalen); + break; + default: + error("key_sign: invalid key type %d", key->type); + return -1; + break; + } } /* @@ -814,61 +970,61 @@ const u_char *signature, u_int signaturelen, const u_char *data, u_int datalen) { - if (signaturelen == 0) - return -1; + if (signaturelen == 0) + return -1; - switch (key->type) { - case KEY_DSA: - return ssh_dss_verify(key, signature, signaturelen, data, datalen); - break; - case KEY_RSA: - return ssh_rsa_verify(key, signature, signaturelen, data, datalen); - break; - default: - error("key_verify: invalid key type %d", key->type); - return -1; - break; - } + switch (key->type) { + case KEY_DSA: + return ssh_dss_verify(key, signature, signaturelen, data, datalen); + break; + case KEY_RSA: + return ssh_rsa_verify(key, signature, signaturelen, data, datalen); + break; + default: + error("key_verify: invalid key type %d", key->type); + return -1; + break; + } } /* Converts a private to a public key */ Key * key_demote(const Key *k) { - Key *pk; + Key *pk; - pk = xmalloc(sizeof(*pk)); - pk->type = k->type; - pk->flags = k->flags; - pk->dsa = NULL; - pk->rsa = NULL; + pk = xmalloc(sizeof(*pk)); + pk->type = k->type; + pk->flags = k->flags; + pk->dsa = NULL; + pk->rsa = NULL; - switch (k->type) { - case KEY_RSA1: - case KEY_RSA: - if ((pk->rsa = RSA_new()) == NULL) - fatal("key_demote: RSA_new failed"); - if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) - fatal("key_demote: BN_dup failed"); - break; - case KEY_DSA: - if ((pk->dsa = DSA_new()) == NULL) - fatal("key_demote: DSA_new failed"); - if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) - fatal("key_demote: BN_dup failed"); - if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) - fatal("key_demote: BN_dup failed"); - break; - default: - fatal("key_free: bad key type %d", k->type); - break; - } + switch (k->type) { + case KEY_RSA1: + case KEY_RSA: + if ((pk->rsa = RSA_new()) == NULL) + fatal("key_demote: RSA_new failed"); + if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL) + fatal("key_demote: BN_dup failed"); + break; + case KEY_DSA: + if ((pk->dsa = DSA_new()) == NULL) + fatal("key_demote: DSA_new failed"); + if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL) + fatal("key_demote: BN_dup failed"); + if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) + fatal("key_demote: BN_dup failed"); + break; + default: + fatal("key_free: bad key type %d", k->type); + break; + } - return (pk); + return (pk); } diff -ruN ssh.orig/key.h ssh/key.h --- ssh.orig/key.h Thu Mar 24 22:02:07 2005 +++ ssh/key.h Fri Mar 25 18:00:56 2005 @@ -1,4 +1,4 @@ -/* $OpenBSD: key.h,v 1.23 2003/11/10 16:23:41 jakob Exp $ */ +/* $OpenBSD: key.h,v 1.23 2003/11/10 16:23:41 jakob Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -29,59 +29,88 @@ #include #include +#ifdef WITH_LDAP_PUBKEY +#include +#include +#endif + typedef struct Key Key; enum types { - KEY_RSA1, - KEY_RSA, - KEY_DSA, - KEY_UNSPEC + KEY_RSA1, + KEY_RSA, + KEY_DSA, + KEY_UNSPEC }; enum fp_type { - SSH_FP_SHA1, - SSH_FP_MD5 + SSH_FP_SHA1, + SSH_FP_MD5 }; enum fp_rep { - SSH_FP_HEX, - SSH_FP_BUBBLEBABBLE + SSH_FP_HEX, + SSH_FP_BUBBLEBABBLE }; /* key is stored in external hardware */ -#define KEY_FLAG_EXT 0x0001 +#define KEY_FLAG_EXT 0x0001 struct Key { - int type; - int flags; - RSA *rsa; - DSA *dsa; + int type; + int flags; + RSA *rsa; + DSA *dsa; }; -Key *key_new(int); -Key *key_new_private(int); -void key_free(Key *); -Key *key_demote(const Key *); -int key_equal(const Key *, const Key *); -char *key_fingerprint(const Key *, enum fp_type, enum fp_rep); -u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); -const char *key_type(const Key *); -int key_write(const Key *, FILE *); -int key_read(Key *, char **); -u_int key_size(const Key *); +Key *key_new(int); +Key *key_new_private(int); +void key_free(Key *); +Key *key_demote(const Key *); +int key_equal(const Key *, const Key *); +char *key_fingerprint(const Key *, enum fp_type, enum fp_rep); +u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *); +const char *key_type(const Key *); +int key_write(const Key *, FILE *); +int key_read(Key *, char **); -Key *key_generate(int, u_int); -Key *key_from_private(const Key *); -int key_type_from_name(char *); +#ifdef WITH_LDAP_PUBKEY -Key *key_from_blob(const u_char *, u_int); -int key_to_blob(const Key *, u_char **, u_int *); -const char *key_ssh_name(const Key *); -int key_names_valid2(const char *); +#define KEY_ATTR "userCertificate" +#define GRP_ATTR "notknownyet" -int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); +/* just nicer to look at */ +typedef struct berval pkdata; -int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); -int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); -int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); +/* next step is to handle fallback on ldap servers */ +typedef struct ldaphost { + char *lpkuurl; /* LDAP users infos in URL format */ + char *lpkufltr; /* UserUrl filter */ + char *lpkgurl; /* LDAP groups infos in URL format */ + char *lpkgfltr; /* GroupUrl filter */ + char *lpkbd; /* bind DN */ + char *lpkbp; /* bind PW :> */ + char *lpksg; /* server group name */ + struct ldaphost *next; +} lh_t; + +pkdata **get_ldap_data(lh_t *, struct passwd *); +#endif + +u_int key_size(const Key *); + +Key *key_generate(int, u_int); +Key *key_from_private(const Key *); +int key_type_from_name(char *); + +Key *key_from_blob(const u_char *, u_int); +int key_to_blob(const Key *, u_char **, u_int *); +const char *key_ssh_name(const Key *); +int key_names_valid2(const char *); + +int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); +int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); + +int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); +int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); +int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); +int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); #endif diff -ruN ssh.orig/servconf.c ssh/servconf.c --- ssh.orig/servconf.c Thu Mar 24 22:02:07 2005 +++ ssh/servconf.c Fri Mar 25 19:31:46 2005 @@ -34,311 +34,369 @@ void initialize_server_options(ServerOptions *options) { - memset(options, 0, sizeof(*options)); - options->num_ports = 0; - options->ports_from_cmdline = 0; - options->listen_addrs = NULL; - options->address_family = -1; - options->num_host_key_files = 0; - options->pid_file = NULL; - options->server_key_bits = -1; - options->login_grace_time = -1; - options->key_regeneration_time = -1; - options->permit_root_login = PERMIT_NOT_SET; - options->ignore_rhosts = -1; - options->ignore_user_known_hosts = -1; - options->print_motd = -1; - options->print_lastlog = -1; - options->x11_forwarding = -1; - options->x11_display_offset = -1; - options->x11_use_localhost = -1; - options->xauth_location = NULL; - options->strict_modes = -1; - options->tcp_keep_alive = -1; - options->log_facility = SYSLOG_FACILITY_NOT_SET; - options->log_level = SYSLOG_LEVEL_NOT_SET; - options->rhosts_rsa_authentication = -1; - options->hostbased_authentication = -1; - options->hostbased_uses_name_from_packet_only = -1; - options->rsa_authentication = -1; - options->pubkey_authentication = -1; - options->kerberos_authentication = -1; - options->kerberos_or_local_passwd = -1; - options->kerberos_ticket_cleanup = -1; - options->kerberos_get_afs_token = -1; - options->gss_authentication=-1; - options->gss_cleanup_creds = -1; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->challenge_response_authentication = -1; - options->permit_empty_passwd = -1; - options->permit_user_env = -1; - options->use_login = -1; - options->compression = -1; - options->allow_tcp_forwarding = -1; - options->num_allow_users = 0; - options->num_deny_users = 0; - options->num_allow_groups = 0; - options->num_deny_groups = 0; - options->ciphers = NULL; - options->macs = NULL; - options->protocol = SSH_PROTO_UNKNOWN; - options->gateway_ports = -1; - options->num_subsystems = 0; - options->max_startups_begin = -1; - options->max_startups_rate = -1; - options->max_startups = -1; - options->max_authtries = -1; - options->banner = NULL; - options->use_dns = -1; - options->client_alive_interval = -1; - options->client_alive_count_max = -1; - options->authorized_keys_file = NULL; - options->authorized_keys_file2 = NULL; - options->num_accept_env = 0; + memset(options, 0, sizeof(*options)); + options->num_ports = 0; + options->ports_from_cmdline = 0; + options->listen_addrs = NULL; + options->address_family = -1; + options->num_host_key_files = 0; + options->pid_file = NULL; + options->server_key_bits = -1; + options->login_grace_time = -1; + options->key_regeneration_time = -1; + options->permit_root_login = PERMIT_NOT_SET; + options->ignore_rhosts = -1; + options->ignore_user_known_hosts = -1; + options->print_motd = -1; + options->print_lastlog = -1; + options->x11_forwarding = -1; + options->x11_display_offset = -1; + options->x11_use_localhost = -1; + options->xauth_location = NULL; + options->strict_modes = -1; + options->tcp_keep_alive = -1; + options->log_facility = SYSLOG_FACILITY_NOT_SET; + options->log_level = SYSLOG_LEVEL_NOT_SET; + options->rhosts_rsa_authentication = -1; + options->hostbased_authentication = -1; + options->hostbased_uses_name_from_packet_only = -1; + options->rsa_authentication = -1; + options->pubkey_authentication = -1; + options->kerberos_authentication = -1; + options->kerberos_or_local_passwd = -1; + options->kerberos_ticket_cleanup = -1; + options->kerberos_get_afs_token = -1; + options->gss_authentication=-1; + options->gss_cleanup_creds = -1; + options->password_authentication = -1; + options->kbd_interactive_authentication = -1; + options->challenge_response_authentication = -1; + options->permit_empty_passwd = -1; + options->permit_user_env = -1; + options->use_login = -1; + options->compression = -1; + options->allow_tcp_forwarding = -1; + options->num_allow_users = 0; + options->num_deny_users = 0; + options->num_allow_groups = 0; + options->num_deny_groups = 0; + options->ciphers = NULL; + options->macs = NULL; + options->protocol = SSH_PROTO_UNKNOWN; + options->gateway_ports = -1; + options->num_subsystems = 0; + options->max_startups_begin = -1; + options->max_startups_rate = -1; + options->max_startups = -1; + options->max_authtries = -1; + options->banner = NULL; + options->use_dns = -1; + options->client_alive_interval = -1; + options->client_alive_count_max = -1; + options->authorized_keys_file = NULL; + options->authorized_keys_file2 = NULL; +#ifdef WITH_LDAP_PUBKEY + options->lpk_opt.lpk_on = -1; + options->lpk_opt.lpk_user_server = NULL; + options->lpk_opt.lpk_user_filter = NULL; + options->lpk_opt.lpk_group_server = NULL; + options->lpk_opt.lpk_group_filter = NULL; + options->lpk_opt.lpk_binddn = NULL; + options->lpk_opt.lpk_bindpw = NULL; + options->lpk_opt.lpk_srvgrp = NULL; + options->lpk_opt.lpk_x509 = -1; +#endif + options->num_accept_env = 0; - /* Needs to be accessable in many places */ - use_privsep = -1; + /* Needs to be accessable in many places */ + use_privsep = -1; } void fill_default_server_options(ServerOptions *options) { - if (options->protocol == SSH_PROTO_UNKNOWN) - options->protocol = SSH_PROTO_1|SSH_PROTO_2; - if (options->num_host_key_files == 0) { - /* fill default hostkeys for protocols */ - if (options->protocol & SSH_PROTO_1) - options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_KEY_FILE; - if (options->protocol & SSH_PROTO_2) { - options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_RSA_KEY_FILE; - options->host_key_files[options->num_host_key_files++] = - _PATH_HOST_DSA_KEY_FILE; - } - } - if (options->num_ports == 0) - options->ports[options->num_ports++] = SSH_DEFAULT_PORT; - if (options->listen_addrs == NULL) - add_listen_addr(options, NULL, 0); - if (options->pid_file == NULL) - options->pid_file = _PATH_SSH_DAEMON_PID_FILE; - if (options->server_key_bits == -1) - options->server_key_bits = 768; - if (options->login_grace_time == -1) - options->login_grace_time = 120; - if (options->key_regeneration_time == -1) - options->key_regeneration_time = 3600; - if (options->permit_root_login == PERMIT_NOT_SET) - options->permit_root_login = PERMIT_YES; - if (options->ignore_rhosts == -1) - options->ignore_rhosts = 1; - if (options->ignore_user_known_hosts == -1) - options->ignore_user_known_hosts = 0; - if (options->print_motd == -1) - options->print_motd = 1; - if (options->print_lastlog == -1) - options->print_lastlog = 1; - if (options->x11_forwarding == -1) - options->x11_forwarding = 0; - if (options->x11_display_offset == -1) - options->x11_display_offset = 10; - if (options->x11_use_localhost == -1) - options->x11_use_localhost = 1; - if (options->xauth_location == NULL) - options->xauth_location = _PATH_XAUTH; - if (options->strict_modes == -1) - options->strict_modes = 1; - if (options->tcp_keep_alive == -1) - options->tcp_keep_alive = 1; - if (options->log_facility == SYSLOG_FACILITY_NOT_SET) - options->log_facility = SYSLOG_FACILITY_AUTH; - if (options->log_level == SYSLOG_LEVEL_NOT_SET) - options->log_level = SYSLOG_LEVEL_INFO; - if (options->rhosts_rsa_authentication == -1) - options->rhosts_rsa_authentication = 0; - if (options->hostbased_authentication == -1) - options->hostbased_authentication = 0; - if (options->hostbased_uses_name_from_packet_only == -1) - options->hostbased_uses_name_from_packet_only = 0; - if (options->rsa_authentication == -1) - options->rsa_authentication = 1; - if (options->pubkey_authentication == -1) - options->pubkey_authentication = 1; - if (options->kerberos_authentication == -1) - options->kerberos_authentication = 0; - if (options->kerberos_or_local_passwd == -1) - options->kerberos_or_local_passwd = 1; - if (options->kerberos_ticket_cleanup == -1) - options->kerberos_ticket_cleanup = 1; - if (options->kerberos_get_afs_token == -1) - options->kerberos_get_afs_token = 0; - if (options->gss_authentication == -1) - options->gss_authentication = 0; - if (options->gss_cleanup_creds == -1) - options->gss_cleanup_creds = 1; - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) - options->kbd_interactive_authentication = 0; - if (options->challenge_response_authentication == -1) - options->challenge_response_authentication = 1; - if (options->permit_empty_passwd == -1) - options->permit_empty_passwd = 0; - if (options->permit_user_env == -1) - options->permit_user_env = 0; - if (options->use_login == -1) - options->use_login = 0; - if (options->compression == -1) - options->compression = 1; - if (options->allow_tcp_forwarding == -1) - options->allow_tcp_forwarding = 1; - if (options->gateway_ports == -1) - options->gateway_ports = 0; - if (options->max_startups == -1) - options->max_startups = 10; - if (options->max_startups_rate == -1) - options->max_startups_rate = 100; /* 100% */ - if (options->max_startups_begin == -1) - options->max_startups_begin = options->max_startups; - if (options->max_authtries == -1) - options->max_authtries = DEFAULT_AUTH_FAIL_MAX; - if (options->use_dns == -1) - options->use_dns = 1; - if (options->client_alive_interval == -1) - options->client_alive_interval = 0; - if (options->client_alive_count_max == -1) - options->client_alive_count_max = 3; - if (options->authorized_keys_file2 == NULL) { - /* authorized_keys_file2 falls back to authorized_keys_file */ - if (options->authorized_keys_file != NULL) - options->authorized_keys_file2 = options->authorized_keys_file; - else - options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; - } - if (options->authorized_keys_file == NULL) - options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; + if (options->protocol == SSH_PROTO_UNKNOWN) + options->protocol = SSH_PROTO_1|SSH_PROTO_2; + if (options->num_host_key_files == 0) { + /* fill default hostkeys for protocols */ + if (options->protocol & SSH_PROTO_1) + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_KEY_FILE; + if (options->protocol & SSH_PROTO_2) { + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_RSA_KEY_FILE; + options->host_key_files[options->num_host_key_files++] = + _PATH_HOST_DSA_KEY_FILE; + } + } + if (options->num_ports == 0) + options->ports[options->num_ports++] = SSH_DEFAULT_PORT; + if (options->listen_addrs == NULL) + add_listen_addr(options, NULL, 0); + if (options->pid_file == NULL) + options->pid_file = _PATH_SSH_DAEMON_PID_FILE; + if (options->server_key_bits == -1) + options->server_key_bits = 768; + if (options->login_grace_time == -1) + options->login_grace_time = 120; + if (options->key_regeneration_time == -1) + options->key_regeneration_time = 3600; + if (options->permit_root_login == PERMIT_NOT_SET) + options->permit_root_login = PERMIT_YES; + if (options->ignore_rhosts == -1) + options->ignore_rhosts = 1; + if (options->ignore_user_known_hosts == -1) + options->ignore_user_known_hosts = 0; + if (options->print_motd == -1) + options->print_motd = 1; + if (options->print_lastlog == -1) + options->print_lastlog = 1; + if (options->x11_forwarding == -1) + options->x11_forwarding = 0; + if (options->x11_display_offset == -1) + options->x11_display_offset = 10; + if (options->x11_use_localhost == -1) + options->x11_use_localhost = 1; + if (options->xauth_location == NULL) + options->xauth_location = _PATH_XAUTH; + if (options->strict_modes == -1) + options->strict_modes = 1; + if (options->tcp_keep_alive == -1) + options->tcp_keep_alive = 1; + if (options->log_facility == SYSLOG_FACILITY_NOT_SET) + options->log_facility = SYSLOG_FACILITY_AUTH; + if (options->log_level == SYSLOG_LEVEL_NOT_SET) + options->log_level = SYSLOG_LEVEL_INFO; + if (options->rhosts_rsa_authentication == -1) + options->rhosts_rsa_authentication = 0; + if (options->hostbased_authentication == -1) + options->hostbased_authentication = 0; + if (options->hostbased_uses_name_from_packet_only == -1) + options->hostbased_uses_name_from_packet_only = 0; + if (options->rsa_authentication == -1) + options->rsa_authentication = 1; + if (options->pubkey_authentication == -1) + options->pubkey_authentication = 1; + if (options->kerberos_authentication == -1) + options->kerberos_authentication = 0; + if (options->kerberos_or_local_passwd == -1) + options->kerberos_or_local_passwd = 1; + if (options->kerberos_ticket_cleanup == -1) + options->kerberos_ticket_cleanup = 1; + if (options->kerberos_get_afs_token == -1) + options->kerberos_get_afs_token = 0; + if (options->gss_authentication == -1) + options->gss_authentication = 0; + if (options->gss_cleanup_creds == -1) + options->gss_cleanup_creds = 1; + if (options->password_authentication == -1) + options->password_authentication = 1; + if (options->kbd_interactive_authentication == -1) + options->kbd_interactive_authentication = 0; + if (options->challenge_response_authentication == -1) + options->challenge_response_authentication = 1; + if (options->permit_empty_passwd == -1) + options->permit_empty_passwd = 0; + if (options->permit_user_env == -1) + options->permit_user_env = 0; + if (options->use_login == -1) + options->use_login = 0; + if (options->compression == -1) + options->compression = 1; + if (options->allow_tcp_forwarding == -1) + options->allow_tcp_forwarding = 1; + if (options->gateway_ports == -1) + options->gateway_ports = 0; + if (options->max_startups == -1) + options->max_startups = 10; + if (options->max_startups_rate == -1) + options->max_startups_rate = 100; /* 100% */ + if (options->max_startups_begin == -1) + options->max_startups_begin = options->max_startups; + if (options->max_authtries == -1) + options->max_authtries = DEFAULT_AUTH_FAIL_MAX; + if (options->use_dns == -1) + options->use_dns = 1; + if (options->client_alive_interval == -1) + options->client_alive_interval = 0; + if (options->client_alive_count_max == -1) + options->client_alive_count_max = 3; + if (options->authorized_keys_file2 == NULL) { + /* authorized_keys_file2 falls back to authorized_keys_file */ + if (options->authorized_keys_file != NULL) + options->authorized_keys_file2 = options->authorized_keys_file; + else + options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2; + } + if (options->authorized_keys_file == NULL) + options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; - /* Turn privilege separation on by default */ - if (use_privsep == -1) - use_privsep = 1; +#ifdef WITH_LDAP_PUBKEY + if (options->lpk_opt.lpk_on == -1) + options->lpk_opt.lpk_on = _DEFAULT_LPK_ON; + if (options->lpk_opt.lpk_user_server == NULL) + options->lpk_opt.lpk_user_server = _DEFAULT_LPK_USRURL; + if (options->lpk_opt.lpk_user_filter == NULL) + options->lpk_opt.lpk_user_filter = _DEFAULT_LPK_USRFLTR; + if (options->lpk_opt.lpk_group_server == NULL) + options->lpk_opt.lpk_group_server = _DEFAULT_LPK_GRPURL; + if (options->lpk_opt.lpk_group_filter == NULL) + options->lpk_opt.lpk_group_filter = _DEFAULT_LPK_GRPFLTR; + if (options->lpk_opt.lpk_binddn == NULL) + options->lpk_opt.lpk_binddn = _DEFAULT_LPK_BINDDN; + if (options->lpk_opt.lpk_bindpw == NULL) + options->lpk_opt.lpk_bindpw = _DEFAULT_LPK_BINDPW; + if (options->lpk_opt.lpk_srvgrp == NULL) + options->lpk_opt.lpk_srvgrp = _DEFAULT_LPK_SGROUP; + if (options->lpk_opt.lpk_x509 == -1) + options->lpk_opt.lpk_x509 = _DEFAULT_LPK_X509; +#endif + + /* Turn privilege separation on by default */ + if (use_privsep == -1) + use_privsep = 1; } /* Keyword tokens. */ typedef enum { - sBadOption, /* == unknown option */ - sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, - sPermitRootLogin, sLogFacility, sLogLevel, - sRhostsRSAAuthentication, sRSAAuthentication, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, - sKerberosGetAFSToken, - sKerberosTgtPassing, sChallengeResponseAuthentication, - sPasswordAuthentication, sKbdInteractiveAuthentication, - sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, - sStrictModes, sEmptyPasswd, sTCPKeepAlive, - sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, - sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, - sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, - sMaxStartups, sMaxAuthTries, - sBanner, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, - sGssAuthentication, sGssCleanupCreds, sAcceptEnv, - sUsePrivilegeSeparation, - sDeprecated, sUnsupported + sBadOption, /* == unknown option */ + sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, + sPermitRootLogin, sLogFacility, sLogLevel, + sRhostsRSAAuthentication, sRSAAuthentication, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, + sKerberosGetAFSToken, + sKerberosTgtPassing, sChallengeResponseAuthentication, + sPasswordAuthentication, sKbdInteractiveAuthentication, + sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, + sStrictModes, sEmptyPasswd, sTCPKeepAlive, + sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression, + sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, + sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, + sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, + sMaxStartups, sMaxAuthTries, + sBanner, sUseDNS, sHostbasedAuthentication, + sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, + sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sGssAuthentication, sGssCleanupCreds, sAcceptEnv, + sUsePrivilegeSeparation, + sDeprecated, sUnsupported +#ifdef WITH_LDAP_PUBKEY + ,sPubkey_from_ldap, sLdap_userver, sLdap_ufilter, sLdap_gserver, sLdap_gfilter, sBinddn, sBindpw, sMgroup +#endif } ServerOpCodes; /* Textual representation of the tokens. */ static struct { - const char *name; - ServerOpCodes opcode; + const char *name; + ServerOpCodes opcode; } keywords[] = { - { "port", sPort }, - { "hostkey", sHostKeyFile }, - { "hostdsakey", sHostKeyFile }, /* alias */ - { "pidfile", sPidFile }, - { "serverkeybits", sServerKeyBits }, - { "logingracetime", sLoginGraceTime }, - { "keyregenerationinterval", sKeyRegenerationTime }, - { "permitrootlogin", sPermitRootLogin }, - { "syslogfacility", sLogFacility }, - { "loglevel", sLogLevel }, - { "rhostsauthentication", sDeprecated }, - { "rhostsrsaauthentication", sRhostsRSAAuthentication }, - { "hostbasedauthentication", sHostbasedAuthentication }, - { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, - { "rsaauthentication", sRSAAuthentication }, - { "pubkeyauthentication", sPubkeyAuthentication }, - { "dsaauthentication", sPubkeyAuthentication }, /* alias */ + { "port", sPort }, + { "hostkey", sHostKeyFile }, + { "hostdsakey", sHostKeyFile }, /* alias */ + { "pidfile", sPidFile }, + { "serverkeybits", sServerKeyBits }, + { "logingracetime", sLoginGraceTime }, + { "keyregenerationinterval", sKeyRegenerationTime }, + { "permitrootlogin", sPermitRootLogin }, + { "syslogfacility", sLogFacility }, + { "loglevel", sLogLevel }, + { "rhostsauthentication", sDeprecated }, + { "rhostsrsaauthentication", sRhostsRSAAuthentication }, + { "hostbasedauthentication", sHostbasedAuthentication }, + { "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly }, + { "rsaauthentication", sRSAAuthentication }, + { "pubkeyauthentication", sPubkeyAuthentication }, + { "dsaauthentication", sPubkeyAuthentication }, /* alias */ #ifdef KRB5 - { "kerberosauthentication", sKerberosAuthentication }, - { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, - { "kerberosticketcleanup", sKerberosTicketCleanup }, - { "kerberosgetafstoken", sKerberosGetAFSToken }, + { "kerberosauthentication", sKerberosAuthentication }, + { "kerberosorlocalpasswd", sKerberosOrLocalPasswd }, + { "kerberosticketcleanup", sKerberosTicketCleanup }, + { "kerberosgetafstoken", sKerberosGetAFSToken }, #else - { "kerberosauthentication", sUnsupported }, - { "kerberosorlocalpasswd", sUnsupported }, - { "kerberosticketcleanup", sUnsupported }, - { "kerberosgetafstoken", sUnsupported }, + { "kerberosauthentication", sUnsupported }, + { "kerberosorlocalpasswd", sUnsupported }, + { "kerberosticketcleanup", sUnsupported }, + { "kerberosgetafstoken", sUnsupported }, #endif - { "kerberostgtpassing", sUnsupported }, - { "afstokenpassing", sUnsupported }, + { "kerberostgtpassing", sUnsupported }, + { "afstokenpassing", sUnsupported }, #ifdef GSSAPI - { "gssapiauthentication", sGssAuthentication }, - { "gssapicleanupcredentials", sGssCleanupCreds }, + { "gssapiauthentication", sGssAuthentication }, + { "gssapicleanupcredentials", sGssCleanupCreds }, #else - { "gssapiauthentication", sUnsupported }, - { "gssapicleanupcredentials", sUnsupported }, + { "gssapiauthentication", sUnsupported }, + { "gssapicleanupcredentials", sUnsupported }, #endif - { "passwordauthentication", sPasswordAuthentication }, - { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, - { "challengeresponseauthentication", sChallengeResponseAuthentication }, - { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */ - { "checkmail", sDeprecated }, - { "listenaddress", sListenAddress }, - { "addressfamily", sAddressFamily }, - { "printmotd", sPrintMotd }, - { "printlastlog", sPrintLastLog }, - { "ignorerhosts", sIgnoreRhosts }, - { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, - { "x11forwarding", sX11Forwarding }, - { "x11displayoffset", sX11DisplayOffset }, - { "x11uselocalhost", sX11UseLocalhost }, - { "xauthlocation", sXAuthLocation }, - { "strictmodes", sStrictModes }, - { "permitemptypasswords", sEmptyPasswd }, - { "permituserenvironment", sPermitUserEnvironment }, - { "uselogin", sUseLogin }, - { "compression", sCompression }, - { "tcpkeepalive", sTCPKeepAlive }, - { "keepalive", sTCPKeepAlive }, /* obsolete alias */ - { "allowtcpforwarding", sAllowTcpForwarding }, - { "allowusers", sAllowUsers }, - { "denyusers", sDenyUsers }, - { "allowgroups", sAllowGroups }, - { "denygroups", sDenyGroups }, - { "ciphers", sCiphers }, - { "macs", sMacs }, - { "protocol", sProtocol }, - { "gatewayports", sGatewayPorts }, - { "subsystem", sSubsystem }, - { "maxstartups", sMaxStartups }, - { "maxauthtries", sMaxAuthTries }, - { "banner", sBanner }, - { "usedns", sUseDNS }, - { "verifyreversemapping", sDeprecated }, - { "reversemappingcheck", sDeprecated }, - { "clientaliveinterval", sClientAliveInterval }, - { "clientalivecountmax", sClientAliveCountMax }, - { "authorizedkeysfile", sAuthorizedKeysFile }, - { "authorizedkeysfile2", sAuthorizedKeysFile2 }, - { "useprivilegeseparation", sUsePrivilegeSeparation}, - { "acceptenv", sAcceptEnv }, - { NULL, sBadOption } + { "passwordauthentication", sPasswordAuthentication }, + { "kbdinteractiveauthentication", sKbdInteractiveAuthentication }, + { "challengeresponseauthentication", sChallengeResponseAuthentication }, + { "skeyauthentication", sChallengeResponseAuthentication }, /* alias */ + { "checkmail", sDeprecated }, + { "listenaddress", sListenAddress }, + { "addressfamily", sAddressFamily }, + { "printmotd", sPrintMotd }, + { "printlastlog", sPrintLastLog }, + { "ignorerhosts", sIgnoreRhosts }, + { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, + { "x11forwarding", sX11Forwarding }, + { "x11displayoffset", sX11DisplayOffset }, + { "x11uselocalhost", sX11UseLocalhost }, + { "xauthlocation", sXAuthLocation }, + { "strictmodes", sStrictModes }, + { "permitemptypasswords", sEmptyPasswd }, + { "permituserenvironment", sPermitUserEnvironment }, + { "uselogin", sUseLogin }, + { "compression", sCompression }, + { "tcpkeepalive", sTCPKeepAlive }, + { "keepalive", sTCPKeepAlive }, /* obsolete alias */ + { "allowtcpforwarding", sAllowTcpForwarding }, + { "allowusers", sAllowUsers }, + { "denyusers", sDenyUsers }, + { "allowgroups", sAllowGroups }, + { "denygroups", sDenyGroups }, + { "ciphers", sCiphers }, + { "macs", sMacs }, + { "protocol", sProtocol }, + { "gatewayports", sGatewayPorts }, + { "subsystem", sSubsystem }, + { "maxstartups", sMaxStartups }, + { "maxauthtries", sMaxAuthTries }, + { "banner", sBanner }, + { "usedns", sUseDNS }, + { "verifyreversemapping", sDeprecated }, + { "reversemappingcheck", sDeprecated }, + { "clientaliveinterval", sClientAliveInterval }, + { "clientalivecountmax", sClientAliveCountMax }, + { "authorizedkeysfile", sAuthorizedKeysFile }, + { "authorizedkeysfile2", sAuthorizedKeysFile2 }, +#ifdef WITH_LDAP_PUBKEY + /* old tokens */ + /* + { "pubkeyfromldap", sPubkey_from_ldap }, + { "ldapserver", sLdap_server }, + { "binddn", sBinddn }, + { "bindpw", sBindpw }, + { "mygroup", sMgroup }, + */ + + /* new one */ + { "lpkOn", sPubkey_from_ldap }, + { "lpkUserUrl", sLdap_userver }, + { "lpkUserFilter", sLdap_ufilter }, + { "lpkGroupUrl", sLdap_gserver }, + { "lpkGroupFilter", sLdap_gfilter }, + { "lpkBindDn", sBinddn }, + { "lpkBindPw", sBindpw }, + { "lpkServerGroup", sMgroup }, + /* later use + { "lpkUseX509", sUseX509 }, + */ +#endif + { "useprivilegeseparation", sUsePrivilegeSeparation}, + { "acceptenv", sAcceptEnv }, + { NULL, sBadOption } }; /* @@ -347,576 +405,656 @@ static ServerOpCodes parse_token(const char *cp, const char *filename, - int linenum) + int linenum) { - u_int i; + u_int i; - for (i = 0; keywords[i].name; i++) - if (strcasecmp(cp, keywords[i].name) == 0) - return keywords[i].opcode; + for (i = 0; keywords[i].name; i++) + if (strcasecmp(cp, keywords[i].name) == 0) + return keywords[i].opcode; - error("%s: line %d: Bad configuration option: %s", - filename, linenum, cp); - return sBadOption; + error("%s: line %d: Bad configuration option: %s", + filename, linenum, cp); + return sBadOption; } static void add_listen_addr(ServerOptions *options, char *addr, u_short port) { - int i; + int i; - if (options->num_ports == 0) - options->ports[options->num_ports++] = SSH_DEFAULT_PORT; - if (options->address_family == -1) - options->address_family = AF_UNSPEC; - if (port == 0) - for (i = 0; i < options->num_ports; i++) - add_one_listen_addr(options, addr, options->ports[i]); - else - add_one_listen_addr(options, addr, port); + if (options->num_ports == 0) + options->ports[options->num_ports++] = SSH_DEFAULT_PORT; + if (options->address_family == -1) + options->address_family = AF_UNSPEC; + if (port == 0) + for (i = 0; i < options->num_ports; i++) + add_one_listen_addr(options, addr, options->ports[i]); + else + add_one_listen_addr(options, addr, port); } static void add_one_listen_addr(ServerOptions *options, char *addr, u_short port) { - struct addrinfo hints, *ai, *aitop; - char strport[NI_MAXSERV]; - int gaierr; + struct addrinfo hints, *ai, *aitop; + char strport[NI_MAXSERV]; + int gaierr; - memset(&hints, 0, sizeof(hints)); - hints.ai_family = options->address_family; - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; - snprintf(strport, sizeof strport, "%u", port); - if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) - fatal("bad addr or host: %s (%s)", - addr ? addr : "", - gai_strerror(gaierr)); - for (ai = aitop; ai->ai_next; ai = ai->ai_next) - ; - ai->ai_next = options->listen_addrs; - options->listen_addrs = aitop; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = options->address_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; + snprintf(strport, sizeof strport, "%u", port); + if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) + fatal("bad addr or host: %s (%s)", + addr ? addr : "", + gai_strerror(gaierr)); + for (ai = aitop; ai->ai_next; ai = ai->ai_next) + ; + ai->ai_next = options->listen_addrs; + options->listen_addrs = aitop; } int process_server_config_line(ServerOptions *options, char *line, const char *filename, int linenum) { - char *cp, **charptr, *arg, *p; - int *intptr, value, i, n; - ServerOpCodes opcode; - u_short port; + char *cp, **charptr, *arg, *p; + int *intptr, value, i, n; + ServerOpCodes opcode; + u_short port; - cp = line; - arg = strdelim(&cp); - /* Ignore leading whitespace */ - if (*arg == '\0') - arg = strdelim(&cp); - if (!arg || !*arg || *arg == '#') - return 0; - intptr = NULL; - charptr = NULL; - opcode = parse_token(arg, filename, linenum); - switch (opcode) { - case sBadOption: - return -1; - case sPort: - /* ignore ports from configfile if cmdline specifies ports */ - if (options->ports_from_cmdline) - return 0; - if (options->listen_addrs != NULL) - fatal("%s line %d: ports must be specified before " - "ListenAddress.", filename, linenum); - if (options->num_ports >= MAX_PORTS) - fatal("%s line %d: too many ports.", - filename, linenum); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing port number.", - filename, linenum); - options->ports[options->num_ports++] = a2port(arg); - if (options->ports[options->num_ports-1] == 0) - fatal("%s line %d: Badly formatted port number.", - filename, linenum); - break; + cp = line; + arg = strdelim(&cp); + /* Ignore leading whitespace */ + if (*arg == '\0') + arg = strdelim(&cp); + if (!arg || !*arg || *arg == '#') + return 0; + intptr = NULL; + charptr = NULL; + opcode = parse_token(arg, filename, linenum); + switch (opcode) { + case sBadOption: + return -1; + case sPort: + /* ignore ports from configfile if cmdline specifies ports */ + if (options->ports_from_cmdline) + return 0; + if (options->listen_addrs != NULL) + fatal("%s line %d: ports must be specified before " + "ListenAddress.", filename, linenum); + if (options->num_ports >= MAX_PORTS) + fatal("%s line %d: too many ports.", + filename, linenum); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing port number.", + filename, linenum); + options->ports[options->num_ports++] = a2port(arg); + if (options->ports[options->num_ports-1] == 0) + fatal("%s line %d: Badly formatted port number.", + filename, linenum); + break; - case sServerKeyBits: - intptr = &options->server_key_bits; + case sServerKeyBits: + intptr = &options->server_key_bits; parse_int: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing integer value.", - filename, linenum); - value = atoi(arg); - if (*intptr == -1) - *intptr = value; - break; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing integer value.", + filename, linenum); + value = atoi(arg); + if (*intptr == -1) + *intptr = value; + break; - case sLoginGraceTime: - intptr = &options->login_grace_time; + case sLoginGraceTime: + intptr = &options->login_grace_time; parse_time: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing time value.", - filename, linenum); - if ((value = convtime(arg)) == -1) - fatal("%s line %d: invalid time value.", - filename, linenum); - if (*intptr == -1) - *intptr = value; - break; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing time value.", + filename, linenum); + if ((value = convtime(arg)) == -1) + fatal("%s line %d: invalid time value.", + filename, linenum); + if (*intptr == -1) + *intptr = value; + break; - case sKeyRegenerationTime: - intptr = &options->key_regeneration_time; - goto parse_time; + case sKeyRegenerationTime: + intptr = &options->key_regeneration_time; + goto parse_time; - case sListenAddress: - arg = strdelim(&cp); - if (arg == NULL || *arg == '\0') - fatal("%s line %d: missing address", - filename, linenum); - p = hpdelim(&arg); - if (p == NULL) - fatal("%s line %d: bad address:port usage", - filename, linenum); - p = cleanhostname(p); - if (arg == NULL) - port = 0; - else if ((port = a2port(arg)) == 0) - fatal("%s line %d: bad port number", filename, linenum); + case sListenAddress: + arg = strdelim(&cp); + if (arg == NULL || *arg == '\0') + fatal("%s line %d: missing address", + filename, linenum); + p = hpdelim(&arg); + if (p == NULL) + fatal("%s line %d: bad address:port usage", + filename, linenum); + p = cleanhostname(p); + if (arg == NULL) + port = 0; + else if ((port = a2port(arg)) == 0) + fatal("%s line %d: bad port number", filename, linenum); - add_listen_addr(options, p, port); + add_listen_addr(options, p, port); - break; + break; - case sAddressFamily: - arg = strdelim(&cp); - intptr = &options->address_family; - if (options->listen_addrs != NULL) - fatal("%s line %d: address family must be specified before " - "ListenAddress.", filename, linenum); - if (strcasecmp(arg, "inet") == 0) - value = AF_INET; - else if (strcasecmp(arg, "inet6") == 0) - value = AF_INET6; - else if (strcasecmp(arg, "any") == 0) - value = AF_UNSPEC; - else - fatal("%s line %d: unsupported address family \"%s\".", - filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + case sAddressFamily: + arg = strdelim(&cp); + intptr = &options->address_family; + if (options->listen_addrs != NULL) + fatal("%s line %d: address family must be specified before " + "ListenAddress.", filename, linenum); + if (strcasecmp(arg, "inet") == 0) + value = AF_INET; + else if (strcasecmp(arg, "inet6") == 0) + value = AF_INET6; + else if (strcasecmp(arg, "any") == 0) + value = AF_UNSPEC; + else + fatal("%s line %d: unsupported address family \"%s\".", + filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; - case sHostKeyFile: - intptr = &options->num_host_key_files; - if (*intptr >= MAX_HOSTKEYS) - fatal("%s line %d: too many host keys specified (max %d).", - filename, linenum, MAX_HOSTKEYS); - charptr = &options->host_key_files[*intptr]; + case sHostKeyFile: + intptr = &options->num_host_key_files; + if (*intptr >= MAX_HOSTKEYS) + fatal("%s line %d: too many host keys specified (max %d).", + filename, linenum, MAX_HOSTKEYS); + charptr = &options->host_key_files[*intptr]; parse_filename: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing file name.", - filename, linenum); - if (*charptr == NULL) { - *charptr = tilde_expand_filename(arg, getuid()); - /* increase optional counter */ - if (intptr != NULL) - *intptr = *intptr + 1; - } - break; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing file name.", + filename, linenum); + if (*charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ + if (intptr != NULL) + *intptr = *intptr + 1; + } + break; - case sPidFile: - charptr = &options->pid_file; - goto parse_filename; + case sPidFile: + charptr = &options->pid_file; + goto parse_filename; - case sPermitRootLogin: - intptr = &options->permit_root_login; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/" - "without-password/forced-commands-only/no " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "without-password") == 0) - value = PERMIT_NO_PASSWD; - else if (strcmp(arg, "forced-commands-only") == 0) - value = PERMIT_FORCED_ONLY; - else if (strcmp(arg, "yes") == 0) - value = PERMIT_YES; - else if (strcmp(arg, "no") == 0) - value = PERMIT_NO; - else - fatal("%s line %d: Bad yes/" - "without-password/forced-commands-only/no " - "argument: %s", filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + case sPermitRootLogin: + intptr = &options->permit_root_login; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/" + "without-password/forced-commands-only/no " + "argument.", filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "without-password") == 0) + value = PERMIT_NO_PASSWD; + else if (strcmp(arg, "forced-commands-only") == 0) + value = PERMIT_FORCED_ONLY; + else if (strcmp(arg, "yes") == 0) + value = PERMIT_YES; + else if (strcmp(arg, "no") == 0) + value = PERMIT_NO; + else + fatal("%s line %d: Bad yes/" + "without-password/forced-commands-only/no " + "argument: %s", filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; - case sIgnoreRhosts: - intptr = &options->ignore_rhosts; + case sIgnoreRhosts: + intptr = &options->ignore_rhosts; parse_flag: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no argument.", - filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no argument: %s", - filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/no argument.", + filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "yes") == 0) + value = 1; + else if (strcmp(arg, "no") == 0) + value = 0; + else + fatal("%s line %d: Bad yes/no argument: %s", + filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; - case sIgnoreUserKnownHosts: - intptr = &options->ignore_user_known_hosts; - goto parse_flag; + case sIgnoreUserKnownHosts: + intptr = &options->ignore_user_known_hosts; + goto parse_flag; - case sRhostsRSAAuthentication: - intptr = &options->rhosts_rsa_authentication; - goto parse_flag; + case sRhostsRSAAuthentication: + intptr = &options->rhosts_rsa_authentication; + goto parse_flag; - case sHostbasedAuthentication: - intptr = &options->hostbased_authentication; - goto parse_flag; + case sHostbasedAuthentication: + intptr = &options->hostbased_authentication; + goto parse_flag; - case sHostbasedUsesNameFromPacketOnly: - intptr = &options->hostbased_uses_name_from_packet_only; - goto parse_flag; + case sHostbasedUsesNameFromPacketOnly: + intptr = &options->hostbased_uses_name_from_packet_only; + goto parse_flag; - case sRSAAuthentication: - intptr = &options->rsa_authentication; - goto parse_flag; + case sRSAAuthentication: + intptr = &options->rsa_authentication; + goto parse_flag; - case sPubkeyAuthentication: - intptr = &options->pubkey_authentication; - goto parse_flag; + case sPubkeyAuthentication: + intptr = &options->pubkey_authentication; + goto parse_flag; - case sKerberosAuthentication: - intptr = &options->kerberos_authentication; - goto parse_flag; + case sKerberosAuthentication: + intptr = &options->kerberos_authentication; + goto parse_flag; - case sKerberosOrLocalPasswd: - intptr = &options->kerberos_or_local_passwd; - goto parse_flag; + case sKerberosOrLocalPasswd: + intptr = &options->kerberos_or_local_passwd; + goto parse_flag; - case sKerberosTicketCleanup: - intptr = &options->kerberos_ticket_cleanup; - goto parse_flag; + case sKerberosTicketCleanup: + intptr = &options->kerberos_ticket_cleanup; + goto parse_flag; - case sKerberosGetAFSToken: - intptr = &options->kerberos_get_afs_token; - goto parse_flag; + case sKerberosGetAFSToken: + intptr = &options->kerberos_get_afs_token; + goto parse_flag; - case sGssAuthentication: - intptr = &options->gss_authentication; - goto parse_flag; + case sGssAuthentication: + intptr = &options->gss_authentication; + goto parse_flag; - case sGssCleanupCreds: - intptr = &options->gss_cleanup_creds; - goto parse_flag; + case sGssCleanupCreds: + intptr = &options->gss_cleanup_creds; + goto parse_flag; - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; - case sKbdInteractiveAuthentication: - intptr = &options->kbd_interactive_authentication; - goto parse_flag; + case sKbdInteractiveAuthentication: + intptr = &options->kbd_interactive_authentication; + goto parse_flag; - case sChallengeResponseAuthentication: - intptr = &options->challenge_response_authentication; - goto parse_flag; + case sChallengeResponseAuthentication: + intptr = &options->challenge_response_authentication; + goto parse_flag; - case sPrintMotd: - intptr = &options->print_motd; - goto parse_flag; + case sPrintMotd: + intptr = &options->print_motd; + goto parse_flag; - case sPrintLastLog: - intptr = &options->print_lastlog; - goto parse_flag; + case sPrintLastLog: + intptr = &options->print_lastlog; + goto parse_flag; - case sX11Forwarding: - intptr = &options->x11_forwarding; - goto parse_flag; + case sX11Forwarding: + intptr = &options->x11_forwarding; + goto parse_flag; - case sX11DisplayOffset: - intptr = &options->x11_display_offset; - goto parse_int; + case sX11DisplayOffset: + intptr = &options->x11_display_offset; + goto parse_int; - case sX11UseLocalhost: - intptr = &options->x11_use_localhost; - goto parse_flag; + case sX11UseLocalhost: + intptr = &options->x11_use_localhost; + goto parse_flag; - case sXAuthLocation: - charptr = &options->xauth_location; - goto parse_filename; + case sXAuthLocation: + charptr = &options->xauth_location; + goto parse_filename; - case sStrictModes: - intptr = &options->strict_modes; - goto parse_flag; + case sStrictModes: + intptr = &options->strict_modes; + goto parse_flag; - case sTCPKeepAlive: - intptr = &options->tcp_keep_alive; - goto parse_flag; + case sTCPKeepAlive: + intptr = &options->tcp_keep_alive; + goto parse_flag; - case sEmptyPasswd: - intptr = &options->permit_empty_passwd; - goto parse_flag; + case sEmptyPasswd: + intptr = &options->permit_empty_passwd; + goto parse_flag; - case sPermitUserEnvironment: - intptr = &options->permit_user_env; - goto parse_flag; + case sPermitUserEnvironment: + intptr = &options->permit_user_env; + goto parse_flag; - case sUseLogin: - intptr = &options->use_login; - goto parse_flag; + case sUseLogin: + intptr = &options->use_login; + goto parse_flag; - case sCompression: - intptr = &options->compression; - goto parse_flag; + case sCompression: + intptr = &options->compression; + goto parse_flag; - case sGatewayPorts: - intptr = &options->gateway_ports; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no/clientspecified " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "clientspecified") == 0) - value = 2; - else if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no/clientspecified " - "argument: %s", filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + case sGatewayPorts: + intptr = &options->gateway_ports; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: missing yes/no/clientspecified " + "argument.", filename, linenum); + value = 0; /* silence compiler */ + if (strcmp(arg, "clientspecified") == 0) + value = 2; + else if (strcmp(arg, "yes") == 0) + value = 1; + else if (strcmp(arg, "no") == 0) + value = 0; + else + fatal("%s line %d: Bad yes/no/clientspecified " + "argument: %s", filename, linenum, arg); + if (*intptr == -1) + *intptr = value; + break; - case sUseDNS: - intptr = &options->use_dns; - goto parse_flag; + case sUseDNS: + intptr = &options->use_dns; + goto parse_flag; - case sLogFacility: - intptr = (int *) &options->log_facility; - arg = strdelim(&cp); - value = log_facility_number(arg); - if (value == SYSLOG_FACILITY_NOT_SET) - fatal("%.200s line %d: unsupported log facility '%s'", - filename, linenum, arg ? arg : ""); - if (*intptr == -1) - *intptr = (SyslogFacility) value; - break; + case sLogFacility: + intptr = (int *) &options->log_facility; + arg = strdelim(&cp); + value = log_facility_number(arg); + if (value == SYSLOG_FACILITY_NOT_SET) + fatal("%.200s line %d: unsupported log facility '%s'", + filename, linenum, arg ? arg : ""); + if (*intptr == -1) + *intptr = (SyslogFacility) value; + break; - case sLogLevel: - intptr = (int *) &options->log_level; - arg = strdelim(&cp); - value = log_level_number(arg); - if (value == SYSLOG_LEVEL_NOT_SET) - fatal("%.200s line %d: unsupported log level '%s'", - filename, linenum, arg ? arg : ""); - if (*intptr == -1) - *intptr = (LogLevel) value; - break; + case sLogLevel: + intptr = (int *) &options->log_level; + arg = strdelim(&cp); + value = log_level_number(arg); + if (value == SYSLOG_LEVEL_NOT_SET) + fatal("%.200s line %d: unsupported log level '%s'", + filename, linenum, arg ? arg : ""); + if (*intptr == -1) + *intptr = (LogLevel) value; + break; - case sAllowTcpForwarding: - intptr = &options->allow_tcp_forwarding; - goto parse_flag; + case sAllowTcpForwarding: + intptr = &options->allow_tcp_forwarding; + goto parse_flag; - case sUsePrivilegeSeparation: - intptr = &use_privsep; - goto parse_flag; + case sUsePrivilegeSeparation: + intptr = &use_privsep; + goto parse_flag; - case sAllowUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_users >= MAX_ALLOW_USERS) - fatal("%s line %d: too many allow users.", - filename, linenum); - options->allow_users[options->num_allow_users++] = - xstrdup(arg); - } - break; + case sAllowUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_users >= MAX_ALLOW_USERS) + fatal("%s line %d: too many allow users.", + filename, linenum); + options->allow_users[options->num_allow_users++] = + xstrdup(arg); + } + break; - case sDenyUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_deny_users >= MAX_DENY_USERS) - fatal( "%s line %d: too many deny users.", - filename, linenum); - options->deny_users[options->num_deny_users++] = - xstrdup(arg); - } - break; + case sDenyUsers: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_deny_users >= MAX_DENY_USERS) + fatal( "%s line %d: too many deny users.", + filename, linenum); + options->deny_users[options->num_deny_users++] = + xstrdup(arg); + } + break; - case sAllowGroups: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_allow_groups >= MAX_ALLOW_GROUPS) - fatal("%s line %d: too many allow groups.", - filename, linenum); - options->allow_groups[options->num_allow_groups++] = - xstrdup(arg); - } - break; + case sAllowGroups: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_allow_groups >= MAX_ALLOW_GROUPS) + fatal("%s line %d: too many allow groups.", + filename, linenum); + options->allow_groups[options->num_allow_groups++] = + xstrdup(arg); + } + break; - case sDenyGroups: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (options->num_deny_groups >= MAX_DENY_GROUPS) - fatal("%s line %d: too many deny groups.", - filename, linenum); - options->deny_groups[options->num_deny_groups++] = xstrdup(arg); - } - break; + case sDenyGroups: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_deny_groups >= MAX_DENY_GROUPS) + fatal("%s line %d: too many deny groups.", + filename, linenum); + options->deny_groups[options->num_deny_groups++] = xstrdup(arg); + } + break; - case sCiphers: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!ciphers_valid(arg)) - fatal("%s line %d: Bad SSH2 cipher spec '%s'.", - filename, linenum, arg ? arg : ""); - if (options->ciphers == NULL) - options->ciphers = xstrdup(arg); - break; + case sCiphers: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (!ciphers_valid(arg)) + fatal("%s line %d: Bad SSH2 cipher spec '%s'.", + filename, linenum, arg ? arg : ""); + if (options->ciphers == NULL) + options->ciphers = xstrdup(arg); + break; - case sMacs: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - if (!mac_valid(arg)) - fatal("%s line %d: Bad SSH2 mac spec '%s'.", - filename, linenum, arg ? arg : ""); - if (options->macs == NULL) - options->macs = xstrdup(arg); - break; + case sMacs: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + if (!mac_valid(arg)) + fatal("%s line %d: Bad SSH2 mac spec '%s'.", + filename, linenum, arg ? arg : ""); + if (options->macs == NULL) + options->macs = xstrdup(arg); + break; - case sProtocol: - intptr = &options->protocol; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing argument.", filename, linenum); - value = proto_spec(arg); - if (value == SSH_PROTO_UNKNOWN) - fatal("%s line %d: Bad protocol spec '%s'.", - filename, linenum, arg ? arg : ""); - if (*intptr == SSH_PROTO_UNKNOWN) - *intptr = value; - break; + case sProtocol: + intptr = &options->protocol; + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing argument.", filename, linenum); + value = proto_spec(arg); + if (value == SSH_PROTO_UNKNOWN) + fatal("%s line %d: Bad protocol spec '%s'.", + filename, linenum, arg ? arg : ""); + if (*intptr == SSH_PROTO_UNKNOWN) + *intptr = value; + break; - case sSubsystem: - if (options->num_subsystems >= MAX_SUBSYSTEMS) { - fatal("%s line %d: too many subsystems defined.", - filename, linenum); - } - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem name.", - filename, linenum); - for (i = 0; i < options->num_subsystems; i++) - if (strcmp(arg, options->subsystem_name[i]) == 0) - fatal("%s line %d: Subsystem '%s' already defined.", - filename, linenum, arg); - options->subsystem_name[options->num_subsystems] = xstrdup(arg); - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing subsystem command.", - filename, linenum); - options->subsystem_command[options->num_subsystems] = xstrdup(arg); - options->num_subsystems++; - break; + case sSubsystem: + if (options->num_subsystems >= MAX_SUBSYSTEMS) { + fatal("%s line %d: too many subsystems defined.", + filename, linenum); + } + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing subsystem name.", + filename, linenum); + for (i = 0; i < options->num_subsystems; i++) + if (strcmp(arg, options->subsystem_name[i]) == 0) + fatal("%s line %d: Subsystem '%s' already defined.", + filename, linenum, arg); + options->subsystem_name[options->num_subsystems] = xstrdup(arg); + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing subsystem command.", + filename, linenum); + options->subsystem_command[options->num_subsystems] = xstrdup(arg); + options->num_subsystems++; + break; - case sMaxStartups: - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: Missing MaxStartups spec.", - filename, linenum); - if ((n = sscanf(arg, "%d:%d:%d", - &options->max_startups_begin, - &options->max_startups_rate, - &options->max_startups)) == 3) { - if (options->max_startups_begin > - options->max_startups || - options->max_startups_rate > 100 || - options->max_startups_rate < 1) - fatal("%s line %d: Illegal MaxStartups spec.", - filename, linenum); - } else if (n != 1) - fatal("%s line %d: Illegal MaxStartups spec.", - filename, linenum); - else - options->max_startups = options->max_startups_begin; - break; + case sMaxStartups: + arg = strdelim(&cp); + if (!arg || *arg == '\0') + fatal("%s line %d: Missing MaxStartups spec.", + filename, linenum); + if ((n = sscanf(arg, "%d:%d:%d", + &options->max_startups_begin, + &options->max_startups_rate, + &options->max_startups)) == 3) { + if (options->max_startups_begin > + options->max_startups || + options->max_startups_rate > 100 || + options->max_startups_rate < 1) + fatal("%s line %d: Illegal MaxStartups spec.", + filename, linenum); + } else if (n != 1) + fatal("%s line %d: Illegal MaxStartups spec.", + filename, linenum); + else + options->max_startups = options->max_startups_begin; + break; - case sMaxAuthTries: - intptr = &options->max_authtries; - goto parse_int; + case sMaxAuthTries: + intptr = &options->max_authtries; + goto parse_int; - case sBanner: - charptr = &options->banner; - goto parse_filename; - /* - * These options can contain %X options expanded at - * connect time, so that you can specify paths like: - * - * AuthorizedKeysFile /etc/ssh_keys/%u - */ - case sAuthorizedKeysFile: - case sAuthorizedKeysFile2: - charptr = (opcode == sAuthorizedKeysFile ) ? - &options->authorized_keys_file : - &options->authorized_keys_file2; - goto parse_filename; + case sBanner: + charptr = &options->banner; + goto parse_filename; + /* + * These options can contain %X options expanded at + * connect time, so that you can specify paths like: + * + * AuthorizedKeysFile /etc/ssh_keys/%u + */ + case sAuthorizedKeysFile: + case sAuthorizedKeysFile2: + charptr = (opcode == sAuthorizedKeysFile ) ? + &options->authorized_keys_file : + &options->authorized_keys_file2; + goto parse_filename; - case sClientAliveInterval: - intptr = &options->client_alive_interval; - goto parse_time; + case sClientAliveInterval: + intptr = &options->client_alive_interval; + goto parse_time; - case sClientAliveCountMax: - intptr = &options->client_alive_count_max; - goto parse_int; + case sClientAliveCountMax: + intptr = &options->client_alive_count_max; + goto parse_int; - case sAcceptEnv: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (strchr(arg, '=') != NULL) - fatal("%s line %d: Invalid environment name.", - filename, linenum); - if (options->num_accept_env >= MAX_ACCEPT_ENV) - fatal("%s line %d: too many allow env.", - filename, linenum); - options->accept_env[options->num_accept_env++] = - xstrdup(arg); - } - break; + case sAcceptEnv: + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (strchr(arg, '=') != NULL) + fatal("%s line %d: Invalid environment name.", + filename, linenum); + if (options->num_accept_env >= MAX_ACCEPT_ENV) + fatal("%s line %d: too many allow env.", + filename, linenum); + options->accept_env[options->num_accept_env++] = + xstrdup(arg); + } + break; - case sDeprecated: - logit("%s line %d: Deprecated option %s", - filename, linenum, arg); - while (arg) - arg = strdelim(&cp); - break; + case sDeprecated: + logit("%s line %d: Deprecated option %s", + filename, linenum, arg); + while (arg) + arg = strdelim(&cp); + break; - case sUnsupported: - logit("%s line %d: Unsupported option %s", - filename, linenum, arg); - while (arg) - arg = strdelim(&cp); - break; - - default: - fatal("%s line %d: Missing handler for opcode %s (%d)", - filename, linenum, arg, opcode); - } - if ((arg = strdelim(&cp)) != NULL && *arg != '\0') - fatal("%s line %d: garbage at end of line; \"%.200s\".", - filename, linenum, arg); - return 0; + case sUnsupported: + logit("%s line %d: Unsupported option %s", + filename, linenum, arg); + while (arg) + arg = strdelim(&cp); + break; +#ifdef WITH_LDAP_PUBKEY + case sPubkey_from_ldap: + intptr = &options->lpk_opt.lpk_on; + goto parse_flag; + case sLdap_userver: + /* arg = strdelim(&cp); */ + p = line; + while(*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing ldap server",filename,linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_user_server=xstrdup(arg); + memset(arg,0,strlen(arg)); + break; + case sLdap_ufilter: + /* arg = strdelim(&cp); */ + p = line; + while(*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing UserUrl filter",filename,linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_user_filter=xstrdup(arg); + memset(arg,0,strlen(arg)); + break; + case sLdap_gserver: + /* arg = strdelim(&cp); */ + p = line; + while(*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing ldap server",filename,linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_group_server=xstrdup(arg); + memset(arg,0,strlen(arg)); + break; + case sLdap_gfilter: + /* arg = strdelim(&cp); */ + p = line; + while(*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing GroupUrl filter",filename,linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_group_filter=xstrdup(arg); + memset(arg,0,strlen(arg)); + break; + case sBinddn: + /* arg = strdelim(&cp); */ + p = line; + while(*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing binddn",filename,linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_binddn = xstrdup(arg); + memset(arg,0,strlen(arg)); + break; + case sBindpw: + /* arg = strdelim(&cp); */ + p = line; + while(*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing bindpw",filename,linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_bindpw=xstrdup(arg); + memset(arg,0,strlen(arg)); + break; + case sMgroup: + p = line; + while (*p++); + arg = p; + if (!arg || *arg == '\0') + fatal("%s line %d: missing groupname",filename, linenum); + arg[strlen(arg)] = '\0'; + options->lpk_opt.lpk_srvgrp = xstrdup(arg); + memset(arg,0,strlen(arg)); + break; +#endif + default: + fatal("%s line %d: Missing handler for opcode %s (%d)", + filename, linenum, arg, opcode); + } + if ((arg = strdelim(&cp)) != NULL && *arg != '\0') + fatal("%s line %d: garbage at end of line; \"%.200s\".", + filename, linenum, arg); + return 0; } /* Reads the server configuration file. */ @@ -924,49 +1062,49 @@ void load_server_config(const char *filename, Buffer *conf) { - char line[1024], *cp; - FILE *f; + char line[1024], *cp; + FILE *f; - debug2("%s: filename %s", __func__, filename); - if ((f = fopen(filename, "r")) == NULL) { - perror(filename); - exit(1); - } - buffer_clear(conf); - while (fgets(line, sizeof(line), f)) { - /* - * Trim out comments and strip whitespace - * NB - preserve newlines, they are needed to reproduce - * line numbers later for error messages - */ - if ((cp = strchr(line, '#')) != NULL) - memcpy(cp, "\n", 2); - cp = line + strspn(line, " \t\r"); + debug2("%s: filename %s", __func__, filename); + if ((f = fopen(filename, "r")) == NULL) { + perror(filename); + exit(1); + } + buffer_clear(conf); + while (fgets(line, sizeof(line), f)) { + /* + * Trim out comments and strip whitespace + * NB - preserve newlines, they are needed to reproduce + * line numbers later for error messages + */ + if ((cp = strchr(line, '#')) != NULL) + memcpy(cp, "\n", 2); + cp = line + strspn(line, " \t\r"); - buffer_append(conf, cp, strlen(cp)); - } - buffer_append(conf, "\0", 1); - fclose(f); - debug2("%s: done config len = %d", __func__, buffer_len(conf)); + buffer_append(conf, cp, strlen(cp)); + } + buffer_append(conf, "\0", 1); + fclose(f); + debug2("%s: done config len = %d", __func__, buffer_len(conf)); } void parse_server_config(ServerOptions *options, const char *filename, Buffer *conf) { - int linenum, bad_options = 0; - char *cp, *obuf, *cbuf; + int linenum, bad_options = 0; + char *cp, *obuf, *cbuf; - debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); + debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); - obuf = cbuf = xstrdup(buffer_ptr(conf)); - linenum = 1; - while ((cp = strsep(&cbuf, "\n")) != NULL) { - if (process_server_config_line(options, cp, filename, - linenum++) != 0) - bad_options++; - } - xfree(obuf); - if (bad_options > 0) - fatal("%s: terminating, %d bad configuration options", - filename, bad_options); + obuf = cbuf = xstrdup(buffer_ptr(conf)); + linenum = 1; + while ((cp = strsep(&cbuf, "\n")) != NULL) { + if (process_server_config_line(options, cp, filename, + linenum++) != 0) + bad_options++; + } + xfree(obuf); + if (bad_options > 0) + fatal("%s: terminating, %d bad configuration options", + filename, bad_options); } diff -ruN ssh.orig/servconf.h ssh/servconf.h --- ssh.orig/servconf.h Thu Mar 24 22:02:07 2005 +++ ssh/servconf.h Fri Mar 25 19:36:02 2005 @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.h,v 1.71 2004/12/23 23:11:00 djm Exp $ */ +/* $OpenBSD: servconf.h,v 1.71 2004/12/23 23:11:00 djm Exp $ */ /* * Author: Tatu Ylonen @@ -18,127 +18,160 @@ #include "buffer.h" -#define MAX_PORTS 256 /* Max # ports. */ +#define MAX_PORTS 256 /* Max # ports. */ -#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ -#define MAX_DENY_USERS 256 /* Max # users on deny list. */ -#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ -#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ -#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ -#define MAX_HOSTKEYS 256 /* Max # hostkeys. */ -#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */ +#define MAX_ALLOW_USERS 256 /* Max # users on allow list. */ +#define MAX_DENY_USERS 256 /* Max # users on deny list. */ +#define MAX_ALLOW_GROUPS 256 /* Max # groups on allow list. */ +#define MAX_DENY_GROUPS 256 /* Max # groups on deny list. */ +#define MAX_SUBSYSTEMS 256 /* Max # subsystems. */ +#define MAX_HOSTKEYS 256 /* Max # hostkeys. */ +#define MAX_ACCEPT_ENV 256 /* Max # of env vars. */ /* permit_root_login */ -#define PERMIT_NOT_SET -1 -#define PERMIT_NO 0 -#define PERMIT_FORCED_ONLY 1 -#define PERMIT_NO_PASSWD 2 -#define PERMIT_YES 3 +#define PERMIT_NOT_SET -1 +#define PERMIT_NO 0 +#define PERMIT_FORCED_ONLY 1 +#define PERMIT_NO_PASSWD 2 +#define PERMIT_YES 3 -#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ +#ifdef WITH_LDAP_PUBKEY +#define _DEFAULT_LDAP_PUBKEY_SERVER NULL +#define _DEFAULT_BASEDN NULL +#define _DEFAULT_LPK_ON 0 +#define _DEFAULT_LPK_X509 0 +#define _DEFAULT_LPK_USRURL NULL +#define _DEFAULT_LPK_USRFLTR "(&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(uid=%s))" +#define _DEFAULT_LPK_GRPURL NULL +#define _DEFAULT_LPK_GRPFLTR "(&(objectclass=posixGroup)(cn=%s)(memberUid=%s))" +#define _DEFAULT_LPK_BINDDN NULL +#define _DEFAULT_LPK_BINDPW NULL +#define _DEFAULT_LPK_SGROUP NULL + +/* later we will change lpk_on and lpk_x509 and other binary flags using a short + * flag register-like with AND/OR operations + */ typedef struct { - u_int num_ports; - u_int ports_from_cmdline; - u_short ports[MAX_PORTS]; /* Port number to listen on. */ - char *listen_addr; /* Address on which the server listens. */ - struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ - int address_family; /* Address family used by the server. */ - char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */ - int num_host_key_files; /* Number of files for host keys. */ - char *pid_file; /* Where to put our pid */ - int server_key_bits;/* Size of the server key. */ - int login_grace_time; /* Disconnect if no auth in this time - * (sec). */ - int key_regeneration_time; /* Server key lifetime (seconds). */ - int permit_root_login; /* PERMIT_*, see above */ - int ignore_rhosts; /* Ignore .rhosts and .shosts. */ - int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts - * for RhostsRsaAuth */ - int print_motd; /* If true, print /etc/motd. */ - int print_lastlog; /* If true, print lastlog */ - int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ - int x11_display_offset; /* What DISPLAY number to start - * searching at */ - int x11_use_localhost; /* If true, use localhost for fake X11 server. */ - char *xauth_location; /* Location of xauth program */ - int strict_modes; /* If true, require string home dir modes. */ - int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ - char *ciphers; /* Supported SSH2 ciphers. */ - char *macs; /* Supported SSH2 macs. */ - int protocol; /* Supported protocol versions. */ - int gateway_ports; /* If true, allow remote connects to forwarded ports. */ - SyslogFacility log_facility; /* Facility for system logging. */ - LogLevel log_level; /* Level for system logging. */ - int rhosts_rsa_authentication; /* If true, permit rhosts RSA - * authentication. */ - int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ - int hostbased_uses_name_from_packet_only; /* experimental */ - int rsa_authentication; /* If true, permit RSA authentication. */ - int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ - int kerberos_authentication; /* If true, permit Kerberos - * authentication. */ - int kerberos_or_local_passwd; /* If true, permit kerberos - * and any other password - * authentication mechanism, - * such as SecurID or - * /etc/passwd */ - int kerberos_ticket_cleanup; /* If true, destroy ticket - * file on logout. */ - int kerberos_get_afs_token; /* If true, try to get AFS token if - * authenticated with Kerberos. */ - int gss_authentication; /* If true, permit GSSAPI authentication */ - int gss_cleanup_creds; /* If true, destroy cred cache on logout */ - int password_authentication; /* If true, permit password - * authentication. */ - int kbd_interactive_authentication; /* If true, permit */ - int challenge_response_authentication; - int permit_empty_passwd; /* If false, do not permit empty - * passwords. */ - int permit_user_env; /* If true, read ~/.ssh/environment */ - int use_login; /* If true, login(1) is used */ - int compression; /* If true, compression is allowed */ - int allow_tcp_forwarding; - u_int num_allow_users; - char *allow_users[MAX_ALLOW_USERS]; - u_int num_deny_users; - char *deny_users[MAX_DENY_USERS]; - u_int num_allow_groups; - char *allow_groups[MAX_ALLOW_GROUPS]; - u_int num_deny_groups; - char *deny_groups[MAX_DENY_GROUPS]; + int lpk_on; /* enable Ldap PubKey */ + char *lpk_user_server; /* ldap URL format where pubkeys are */ + char *lpk_user_filter; /* User filter */ + char *lpk_group_server; /* ldap URL format where pubkeys are */ + char *lpk_group_filter; /* Group filter */ + char *lpk_binddn; /* ldap base dn where users resides */ + char *lpk_bindpw; /* ldap bind passwd */ + char *lpk_srvgrp; /* ldap server group name, NULL if deactivated */ + int lpk_x509; +} ldap_opt; +#endif - u_int num_subsystems; - char *subsystem_name[MAX_SUBSYSTEMS]; - char *subsystem_command[MAX_SUBSYSTEMS]; +#define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ - u_int num_accept_env; - char *accept_env[MAX_ACCEPT_ENV]; +typedef struct { + u_int num_ports; + u_int ports_from_cmdline; + u_short ports[MAX_PORTS]; /* Port number to listen on. */ + char *listen_addr; /* Address on which the server listens. */ + struct addrinfo *listen_addrs; /* Addresses on which the server listens. */ + int address_family; /* Address family used by the server. */ + char *host_key_files[MAX_HOSTKEYS]; /* Files containing host keys. */ + int num_host_key_files; /* Number of files for host keys. */ + char *pid_file; /* Where to put our pid */ + int server_key_bits;/* Size of the server key. */ + int login_grace_time; /* Disconnect if no auth in this time + * (sec). */ + int key_regeneration_time; /* Server key lifetime (seconds). */ + int permit_root_login; /* PERMIT_*, see above */ + int ignore_rhosts; /* Ignore .rhosts and .shosts. */ + int ignore_user_known_hosts; /* Ignore ~/.ssh/known_hosts + * for RhostsRsaAuth */ + int print_motd; /* If true, print /etc/motd. */ + int print_lastlog; /* If true, print lastlog */ + int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ + int x11_display_offset; /* What DISPLAY number to start + * searching at */ + int x11_use_localhost; /* If true, use localhost for fake X11 server. */ + char *xauth_location; /* Location of xauth program */ + int strict_modes; /* If true, require string home dir modes. */ + int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ + char *ciphers; /* Supported SSH2 ciphers. */ + char *macs; /* Supported SSH2 macs. */ + int protocol; /* Supported protocol versions. */ + int gateway_ports; /* If true, allow remote connects to forwarded ports. */ + SyslogFacility log_facility; /* Facility for system logging. */ + LogLevel log_level; /* Level for system logging. */ + int rhosts_rsa_authentication; /* If true, permit rhosts RSA + * authentication. */ + int hostbased_authentication; /* If true, permit ssh2 hostbased auth */ + int hostbased_uses_name_from_packet_only; /* experimental */ + int rsa_authentication; /* If true, permit RSA authentication. */ + int pubkey_authentication; /* If true, permit ssh2 pubkey authentication. */ + int kerberos_authentication; /* If true, permit Kerberos + * authentication. */ + int kerberos_or_local_passwd; /* If true, permit kerberos + * and any other password + * authentication mechanism, + * such as SecurID or + * /etc/passwd */ + int kerberos_ticket_cleanup; /* If true, destroy ticket + * file on logout. */ + int kerberos_get_afs_token; /* If true, try to get AFS token if + * authenticated with Kerberos. */ + int gss_authentication; /* If true, permit GSSAPI authentication */ + int gss_cleanup_creds; /* If true, destroy cred cache on logout */ + int password_authentication; /* If true, permit password + * authentication. */ + int kbd_interactive_authentication; /* If true, permit */ + int challenge_response_authentication; + int permit_empty_passwd; /* If false, do not permit empty + * passwords. */ + int permit_user_env; /* If true, read ~/.ssh/environment */ + int use_login; /* If true, login(1) is used */ + int compression; /* If true, compression is allowed */ + int allow_tcp_forwarding; + u_int num_allow_users; + char *allow_users[MAX_ALLOW_USERS]; + u_int num_deny_users; + char *deny_users[MAX_DENY_USERS]; + u_int num_allow_groups; + char *allow_groups[MAX_ALLOW_GROUPS]; + u_int num_deny_groups; + char *deny_groups[MAX_DENY_GROUPS]; - int max_startups_begin; - int max_startups_rate; - int max_startups; - int max_authtries; - char *banner; /* SSH-2 banner message */ - int use_dns; - int client_alive_interval; /* - * poke the client this often to - * see if it's still there - */ - int client_alive_count_max; /* - * If the client is unresponsive - * for this many intervals above, - * disconnect the session - */ + u_int num_subsystems; + char *subsystem_name[MAX_SUBSYSTEMS]; + char *subsystem_command[MAX_SUBSYSTEMS]; - char *authorized_keys_file; /* File containing public keys */ - char *authorized_keys_file2; + u_int num_accept_env; + char *accept_env[MAX_ACCEPT_ENV]; + + int max_startups_begin; + int max_startups_rate; + int max_startups; + int max_authtries; + char *banner; /* SSH-2 banner message */ + int use_dns; + int client_alive_interval; /* + * poke the client this often to + * see if it's still there + */ + int client_alive_count_max; /* + * If the client is unresponsive + * for this many intervals above, + * disconnect the session + */ + + char *authorized_keys_file; /* File containing public keys */ + char *authorized_keys_file2; +#ifdef WITH_LDAP_PUBKEY + ldap_opt lpk_opt; +#endif } ServerOptions; -void initialize_server_options(ServerOptions *); -void fill_default_server_options(ServerOptions *); -int process_server_config_line(ServerOptions *, char *, const char *, int); -void load_server_config(const char *, Buffer *); -void parse_server_config(ServerOptions *, const char *, Buffer *); +void initialize_server_options(ServerOptions *); +void fill_default_server_options(ServerOptions *); +int process_server_config_line(ServerOptions *, char *, const char *, int); +void load_server_config(const char *, Buffer *); +void parse_server_config(ServerOptions *, const char *, Buffer *); -#endif /* SERVCONF_H */ +#endif /* SERVCONF_H */ diff -ruN ssh.orig/ssh_config.5 ssh/ssh_config.5 --- ssh.orig/ssh_config.5 Thu Mar 24 22:02:07 2005 +++ ssh/ssh_config.5 Fri Mar 25 19:41:42 2005 @@ -861,6 +861,54 @@ program. The default is .Pa /usr/X11R6/bin/xauth . +.It Cm lpkOn +Enable LDAP public key resolution. The argument must be +.Dq yes +or +.Dq no . +.It Cm lpkGroupUrl/lpkUserUrl +Specifies LDAP User/Group in URL format. the following form may be used: +.Pp +.Bl -item -offset indent -compact +.It +.Cm lpkUserUrl +.Sm off +.Ar ldap://127.0.0.1/ou=users,dc=mydomain,dc=net +.Sm on +.It +.Cm lpkGroupUrl +.Sm off +.Ar ldap://127.0.0.1/ou=groups,dc=mydomain,dc=net +.Sm on +.El +.Pp +.It Cm lpkUserFilter/lpkGroupFilter +Specifies a filter to apply on searches +.Pp +.Bl -item -offset indent -compact +.It +.Cm lpkUserFilter +.Sm off +.Ar (&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(uid=%s)) +.Sm on +.It +.Cm lpkGroupFilter +.Sm off +.Ar (&(objectclass=posixGroup)(cn=%s)(memberUid=%s)) +.Sm on +.El +.Pp +.It Cm lpkBindDn +Specifies a LDAP bind DN to use when doing ldap lookups. +.It Cm lpkBindPw +Specifies a LDAP bind Password associated to the previous token. +.It Cm lpkServerGroup +Specifies the group is the host is part of. +.It Cm lpkUseX509 +Enable X509 public key support The argument must be +.Dq yes +or +.Dq no . .El .Sh FILES .Bl -tag -width Ds diff -ruN ssh.orig/sshd_config ssh/sshd_config --- ssh.orig/sshd_config Thu Mar 24 22:02:07 2005 +++ ssh/sshd_config Fri Mar 25 19:37:42 2005 @@ -1,4 +1,4 @@ -# $OpenBSD: sshd_config,v 1.70 2004/12/23 23:11:00 djm Exp $ +# $OpenBSD: sshd_config,v 1.70 2004/12/23 23:11:00 djm Exp $ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. @@ -38,7 +38,7 @@ #RSAAuthentication yes #PubkeyAuthentication yes -#AuthorizedKeysFile .ssh/authorized_keys +#AuthorizedKeysFile .ssh/authorized_keys # For this to work you will also need host keys in /etc/ssh/ssh_known_hosts #RhostsRSAAuthentication no @@ -67,6 +67,18 @@ #GSSAPIAuthentication no #GSSAPICleanupCredentials yes +# LDAP PubKeys options +# entries in your LDAP must be posixAccount & strongAuthenticationUser +lpkOn no +#lpkUserUrl ldap://127.0.0.1/ou=users,dc=mydomain,dc=net +#lpkUserFilter (&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(uid=%s)) #default value +#lpkGroupUrl ldap://127.0.0.1/ou=groups,dc=mydomain,dc=net +#lpkGroupFilter (&(objectclass=posixGroup)(cn=%s)(memberUid=%s)) #default value +#lpkBindDn cn=Manager,dc=mydomain,dc=net +#lpkBindPw secret +#lpkServerGroup unix +#lpkUseX509 no #NOT implemented yet + #AllowTcpForwarding yes #GatewayPorts no #X11Forwarding no @@ -89,4 +101,4 @@ #Banner /some/path # override default of no subsystems -Subsystem sftp /usr/libexec/sftp-server +Subsystem sftp /usr/libexec/sftp-server