diff -ru openssh-3.6.1p1/auth2-pubkey.c openssh-3.6.1p1-ldappubkey/auth2-pubkey.c --- openssh-3.6.1p1/auth2-pubkey.c Thu Jun 6 22:27:56 2002 +++ openssh-3.6.1p1-ldappubkey/auth2-pubkey.c Thu Apr 17 11:53:03 2003 @@ -174,12 +174,46 @@ struct stat st; Key *found; char *fp; +#ifdef WITH_LDAP_PUBKEY + lh host; +#endif if (pw == NULL) return 0; /* Temporarily use the user's uid. */ temporarily_use_uid(pw); +#ifdef WITH_LDAP_PUBKEY + found_key = 0; + /* allocate a new key type */ + found = key_new(key->type); + + /* first check if the options is enabled, then try.. */ + debug("trying LDAP first uid=%s",pw->pw_name); + + /* lets add it */ + host.url = options.myldap_opt.ldap_server; + host.binddn = options.myldap_opt.binddn; + host.bindpw = options.myldap_opt.bindpw; + host.mgroup = options.myldap_opt.mgroup; + + if(options.myldap_opt.pubkey_from_ldap + &&(key_ldap_read(found,pw->pw_name,&host) != 1)) { + debug2("LDAP pubkey failed!!!"); + debug2("URL: %s !!",options.myldap_opt.ldap_server); + } + + if (key_equal(found,key)) { + found_key = 1; + debug("matching key found on LDAP, line %lu",linenum); + fp = key_fingerprint(found,SSH_FP_MD5, SSH_FP_HEX); + verbose("Found matching %s key: %s",key_type(found),fp); + xfree(fp); + restore_uid(); + key_free(found); + return found_key; + } +#endif debug("trying public key file %s", file); @@ -189,6 +223,7 @@ restore_uid(); return 0; } + /* Open the file containing the authorized keys. */ f = fopen(file, "r"); if (!f) { @@ -196,6 +231,7 @@ restore_uid(); return 0; } + if (options.strict_modes && secure_filename(f, file, pw, line, sizeof(line)) != 0) { fclose(f); @@ -204,8 +240,11 @@ return 0; } + /* found_key = 0; found = key_new(key->type); + old place of found_key = 0; + */ while (fgets(line, sizeof(line), f)) { char *cp, *options = NULL; diff -ru openssh-3.6.1p1/key.c openssh-3.6.1p1-ldappubkey/key.c --- openssh-3.6.1p1/key.c Mon Feb 24 02:01:41 2003 +++ openssh-3.6.1p1-ldappubkey/key.c Thu Apr 17 11:48:00 2003 @@ -36,6 +36,25 @@ #include +#ifdef WITH_LDAP_PUBKEY +#include +#include + +#define PORT LDAP_PORT +#define LINEMAX 1024 +/* + * 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. + */ +#define OBJCLASS "objectclass=strongAuthenticationUser" +#define BASE_REQ "ou=users,dc=foobar,dc=net" +#endif + #include "xmalloc.h" #include "key.h" #include "rsa.h" @@ -372,6 +391,217 @@ OPENSSL_free(buf); return 1; } + +#ifdef WITH_LDAP_PUBKEY +/* returns 1 ok, -1 error */ +int +/* key_ldap_read(Key *ret, char *uid, char *url, char *binddn, char *bindpw) */ +key_ldap_read(Key *ret, char *uid, lh *host) +{ + Key *k; + LDAP *ld; + LDAPMessage *res,*e; + LDAPURLDesc *urlstruct; + char *a,*urlssl,objbuf[LINEMAX]; + struct berval **vals; + BerElement *ptr; + int version, rc, j, i, success = -1, ssl_size = 0; + + /* version to 3 */ + version = LDAP_VERSION3; + + /* url based ldap://hostport/dn[?attrs[?scope[?filter[?exts]]]] */ + rc = ldap_is_ldap_url(host->url); + if (rc < 0) { + error("key_ldap_read: ldap_is_ldap_url() -> ldap is not an url"); + + success = -1; + return success; + } + + rc = ldap_url_parse(host->url,&urlstruct); + if (rc) { + error("key_ldap_read: ldap_url_parse() -> ldap couldn't be parsed"); + + success = -1; + return success; + } + + ssl_size = strlen(urlstruct->lud_scheme)+strlen(urlstruct->lud_host)+10; + + urlssl = (char *) malloc( ssl_size * sizeof(char) ); + if (!urlssl) { + error("key_ldap_read: malloc()"); + + /* free what has been allocated */ + ldap_free_urldesc(urlstruct); + + success = -1; + return success; + } + memset(urlssl,0,ssl_size); + snprintf(urlssl,ssl_size,"%s://%s:%d",urlstruct->lud_scheme,urlstruct->lud_host,urlstruct->lud_port); + + /* open ldap connection */ + ld = ldap_init(urlstruct->lud_host,urlstruct->lud_port); + if(!ld) { + error("key_ldap_read: ldap_init()"); + + /* free what has been allocated */ + free(urlssl); + ldap_free_urldesc(urlstruct); + + success = -1; + return success; + } + + /* setting V3 proto otherwise TLS impossible */ + if (ldap_set_option(ld,LDAP_OPT_PROTOCOL_VERSION,&version) != LDAP_OPT_SUCCESS) { + error("key_ldap_read: ldap couldn't set version for TLS/SSL"); + + /* free what has been allocated */ + free(urlssl); + ldap_free_urldesc(urlstruct); + + success = -1; + return success; + } + /* HERE CHOOSE SSL/TLS use the scheme and look for the magic 's' ;) */ + if (urlstruct->lud_scheme[strlen(urlstruct->lud_scheme)-1] == 's') { + if (ldap_initialize(&ld, urlssl) != LDAP_SUCCESS) { + error("key_ldap_read: ldap_initialize()"); + + /* free what has been allocated */ + free(urlssl); + ldap_free_urldesc(urlstruct); + + success = -1; + return success; + } + } else { + if ( (ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS)) { + ldap_perror( ld, "key_ldap_read: (TLS) ldap_start_tls" ); + /* recover to normal connection */ + ld = ldap_init(urlstruct->lud_host,urlstruct->lud_port); + if(!ld) { + error("key_ldap_read: ldap_init()"); + + /* free what has been allocated */ + free(urlssl); + ldap_free_urldesc(urlstruct); + + success = -1; + return success; + } + /* use_ssl=1; */ + } + } + + /* anonymous bind pubkey can be retrieved by anybody */ + if (ldap_simple_bind_s(ld,host->binddn,host->bindpw) != LDAP_SUCCESS) { + error("key_ldap_read: ldap_simple_bind_s()"); + + /* free what has been allocated */ + free(urlssl); + ldap_free_urldesc(urlstruct); + + success = -1; + return success; + } + + /* start ldap search */ + if (!uid) + return success; + + /* + * + * The user need to have posixAccount & strongAuthenticationuser attributes + * to accept the challenge. + * posixAccount & strongAuthenticationuser + uid is member of configured group. + * ldap user entries MUST respect our standard description. + * objectclass still hardcoded, hope to change this soon . + * + */ + if (host->mgroup) + snprintf(objbuf,LINEMAX,"(&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(&(cn=*%s*)(uid=%s)))",host->mgroup,uid); + else + snprintf(objbuf,LINEMAX,"(&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(uid=%s))",uid); + + /* New filter group inclusive depend on the configuration */ + /* (&(objectclass=posixAccount)(objectclass=strongAuthenticationUser)(&(cn=*groupname*)(uid=eau))) */ + + ldap_search_s(ld,urlstruct->lud_dn,LDAP_SCOPE_SUBTREE,objbuf,NULL,0,&res); + i = ldap_count_entries(ld,res); + + 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) { + vals=ldap_get_values_len(ld,e,a); + for(j = 0; vals[j] != NULL; j++) { + /* value is here :) vals[j] */ + k = key_from_blob((unsigned char *)vals[j]->bv_val,(int)vals[j]->bv_len); + + if (!k) { + error("key_read: key_from_blob LDAP failed"); + + ldap_value_free_len(vals); + ldap_free_urldesc(urlstruct); + free(urlssl); + + return (-1); + } + + /* i dont have type ?!?!?! */ + if (k->type != KEY_DSA) { + error("key_read: type mismatch: encoding error"); + + ldap_value_free_len(vals); + ldap_free_urldesc(urlstruct); + free(urlssl); + key_free(k); + + return (-1); + } + + if (ret->type == KEY_RSA) { + error("LDAP doesnt handle RSA keys yet"); + + /* freeing everything */ + ldap_value_free_len(vals); + ldap_free_urldesc(urlstruct); + free(urlssl); + key_free(k); + + return (-1); + } else { + if (ret->dsa != NULL) + DSA_free(ret->dsa); + ret->dsa = k->dsa; + k->dsa = NULL; + DSA_print_fp(stderr,ret->dsa,8); + + /* freeing everything */ + ldap_value_free_len(vals); + ldap_free_urldesc(urlstruct); + free(urlssl); + key_free(k); + + success = 1; + return success; + } + } + ldap_value_free_len(vals); + key_free(k); + } + } + } + ldap_free_urldesc(urlstruct); + free(urlssl); + return success; +} +#endif /* returns 1 ok, -1 error */ int diff -ru openssh-3.6.1p1/key.h openssh-3.6.1p1-ldappubkey/key.h --- openssh-3.6.1p1/key.h Mon Feb 24 02:01:41 2003 +++ openssh-3.6.1p1-ldappubkey/key.h Thu Apr 17 11:48:05 2003 @@ -64,6 +64,18 @@ char *key_type(Key *); int key_write(Key *, FILE *); int key_read(Key *, char **); +#ifdef WITH_LDAP_PUBKEY +/* next step is to handle fallback on ldap servers */ +typedef struct ldaphost { + char *url; /* LDAP infos in URL format */ + char *binddn; /* bind DN */ + char *bindpw; /* obvious :> */ + char *mgroup; /* server group name */ + struct ldaphost *next; +} lh; + +int key_ldap_read(Key *, char *, lh *); +#endif u_int key_size(Key *); Key *key_generate(int, u_int); diff -ru openssh-3.6.1p1/servconf.c openssh-3.6.1p1-ldappubkey/servconf.c --- openssh-3.6.1p1/servconf.c Mon Feb 24 02:04:34 2003 +++ openssh-3.6.1p1-ldappubkey/servconf.c Thu Apr 17 12:04:42 2003 @@ -123,6 +123,13 @@ options->client_alive_count_max = -1; options->authorized_keys_file = NULL; options->authorized_keys_file2 = NULL; +#ifdef WITH_LDAP_PUBKEY + options->myldap_opt.pubkey_from_ldap = -1; + options->myldap_opt.ldap_server = NULL; + options->myldap_opt.binddn = NULL; + options->myldap_opt.bindpw = NULL; + options->myldap_opt.mgroup = NULL; +#endif /* Needs to be accessable in many places */ use_privsep = -1; @@ -255,6 +262,18 @@ } if (options->authorized_keys_file == NULL) options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS; +#ifdef WITH_LDAP_PUBKEY + if (options->myldap_opt.pubkey_from_ldap == -1) + options->myldap_opt.pubkey_from_ldap = 0; + if (options->myldap_opt.ldap_server == NULL) + options->myldap_opt.ldap_server = _DEFAULT_LDAP_PUBKEY_SERVER; + if (options->myldap_opt.binddn == NULL) + options->myldap_opt.binddn = _DEFAULT_BINDDN; + if (options->myldap_opt.bindpw == NULL) + options->myldap_opt.bindpw = _DEFAULT_BINDPW; + if (options->myldap_opt.mgroup == NULL) + options->myldap_opt.mgroup = _DEFAULT_MGROUP; +#endif /* Turn privilege separation on by default */ if (use_privsep == -1) @@ -303,6 +322,9 @@ sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, sUsePrivilegeSeparation, sDeprecated, sUnsupported +#ifdef WITH_LDAP_PUBKEY + ,sPubkey_from_ldap, sLdap_server, sBinddn, sBindpw, sMgroup +#endif } ServerOpCodes; /* Textual representation of the tokens. */ @@ -379,6 +401,13 @@ { "clientalivecountmax", sClientAliveCountMax }, { "authorizedkeysfile", sAuthorizedKeysFile }, { "authorizedkeysfile2", sAuthorizedKeysFile2 }, +#ifdef WITH_LDAP_PUBKEY + { "pubkeyfromldap", sPubkey_from_ldap }, + { "ldapserver", sLdap_server }, + { "binddn", sBinddn }, + { "bindpw", sBindpw }, + { "mygroup", sMgroup }, +#endif { "useprivilegeseparation", sUsePrivilegeSeparation}, { NULL, sBadOption } }; @@ -915,6 +944,54 @@ while (arg) arg = strdelim(&cp); break; +#ifdef WITH_LDAP_PUBKEY + case sPubkey_from_ldap: + intptr = &options->myldap_opt.pubkey_from_ldap; + goto parse_flag; + case sLdap_server: + /* 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)-1] = '\0'; + options->myldap_opt.ldap_server=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)-1] = '\0'; + options->myldap_opt.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)-1] = '\0'; + options->myldap_opt.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) - 1] = '\0'; + options->myldap_opt.mgroup = xstrdup(arg); + memset(arg,0,strlen(arg)); + break; +#endif default: fatal("%s line %d: Missing handler for opcode %s (%d)", diff -ru openssh-3.6.1p1/servconf.h openssh-3.6.1p1-ldappubkey/servconf.h --- openssh-3.6.1p1/servconf.h Thu Aug 1 03:28:39 2002 +++ openssh-3.6.1p1-ldappubkey/servconf.h Thu Apr 17 11:57:48 2003 @@ -32,6 +32,22 @@ #define PERMIT_NO_PASSWD 2 #define PERMIT_YES 3 +#ifdef WITH_LDAP_PUBKEY +#define _DEFAULT_LDAP_PUBKEY_SERVER "localhost" +#define _DEFAULT_BASEDN "ou=People,dc=company,dc=net" +#define _DEFAULT_BINDDN NULL +#define _DEFAULT_BINDPW NULL +#define _DEFAULT_MGROUP NULL + +typedef struct { + int pubkey_from_ldap; + char *ldap_server; /* ldap URL format where pubkeys are */ + char *binddn; /* ldap base dn where users resides */ + char *bindpw; /* ldap bind passwd */ + char *mgroup; /* ldap server group name, NULL if deactivated */ +} ldap_opt; +#endif + typedef struct { u_int num_ports; @@ -132,6 +148,9 @@ char *authorized_keys_file; /* File containing public keys */ char *authorized_keys_file2; int use_pam; /* Enable auth via PAM */ +#ifdef WITH_LDAP_PUBKEY + ldap_opt myldap_opt; +#endif } ServerOptions; void initialize_server_options(ServerOptions *); diff -ru openssh-3.6.1p1/sshd_config openssh-3.6.1p1-ldappubkey/sshd_config --- openssh-3.6.1p1/sshd_config Fri Sep 27 05:21:58 2002 +++ openssh-3.6.1p1-ldappubkey/sshd_config Thu Apr 17 12:21:43 2003 @@ -89,5 +89,13 @@ #Banner /some/path #VerifyReverseMapping no +# here is the new patched ldap related tokens +# entries in your LDAP must be posixAccount & strongAuthenticationUser +pubkeyfromldap yes +ldapserver ldap://localhost/ou=users,dc=cuckoos,dc=net +binddn cn=Manager,dc=cuckoos,dc=net +bindpw secret +mygroup unixmail + # override default of no subsystems Subsystem sftp /usr/libexec/sftp-server