Hello! pwent_mapper_find_user() searches through all available passwd db entries to find an user. This takes a very long time, if you have many users (10000). Additionally, if you have nss-ldap configured, it transfers a large amount of data (which is expensive on mobile connections...).
Included you find a patch to speed up user finding for the pwent_mapper. It first tries to find a user directly by calling getpwnam() with the found CN. If this fails, the old mechanism is used. (I think the second step could probably even be removed: I can't find a situation where the getpwnam() does not work.) Please have a look at the patch. If it's OK please include it in further pam_pkcs11 releases (so I don't have to patch every new pam_pkcs11 release on my own ;-) ). Kind regards Dominik Fischer ---8<-----8<---- Index: src/mappers/pwent_mapper.c =================================================================== --- src/mappers/pwent_mapper.c (Revision 488) +++ src/mappers/pwent_mapper.c (Arbeitskopie) @@ -64,29 +64,45 @@ parses the certificate and return the _first_ CN entry found, or NULL */ static char * pwent_mapper_find_user(X509 *x509,void *context, int *match) { - char *str; + char *str; + struct passwd *pw; char *found_user = NULL; - char **entries = cert_info(x509,CERT_CN,ALGORITHM_NULL); - if (!entries) { - DBG("get_common_name() failed"); - return NULL; - } - /* parse list of uids until match */ - for (str=*entries; str ; str=*++entries) { - DBG1("trying to find pw_entry for cn '%s'",str); - found_user= search_pw_entry((const char *)str,ignorecase); - if (!found_user) { - DBG1("CN entry '%s' not found in pw database. Trying next",str); - continue; - } else { - DBG1("Found CN in pw database for user '%s'",found_user); - *match = 1; - /* WJG: Usually allocated mem is returned - memleak/problem? */ - return found_user; - } - } + char **entries = cert_info(x509,CERT_CN,ALGORITHM_NULL); + if (!entries) { + DBG("get_common_name() failed"); + return NULL; + } + DBG1("trying to find pw_entry for cn '%s'",str); + /* First: direct try to avoid long searchtime or massive network traffic + * for large amount of users in pw database. + * (Think of 10000 or more users, mobile connection to ldap, etc.) + */ + for (str=*entries; str ; str=*++entries) { + pw = getpwnam(str); + if (pw == NULL) { + DBG1("Entry for %s not found (direct).", (const char *) str); + } else { + DBG1("Found CN in pw database for user %s (direct).", (const char *) str); + return pw->pw_name; + } + } + + /* Second: search all entries (old behaviour) */ + /* parse list of uids until match */ + for (str=*entries; str ; str=*++entries) { + found_user = search_pw_entry((const char *)str,ignorecase); + if (!found_user) { + DBG1("CN entry '%s' not found in pw database. Trying next",str); + continue; + } else { + DBG1("Found CN in pw database for user '%s'",found_user); + *match = 1; + /* WJG: Usually allocated mem is returned - memleak/problem? */ + return found_user; + } + } DBG("No pw entry maps to any provided Common Name"); - return NULL; + return NULL; } /* _______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel