diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2006-11-11 15:02:25 +0100 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2006-11-11 15:02:25 +0100 |
commit | db14b113e055fa7ab006cfe1c04961bba19a85de (patch) | |
tree | 4ffec7243dd1c56f3fdfddbe294e7451c408f384 /server | |
parent | bffd85ce667130419ddb381421e1a524f490b981 (diff) |
simplify some functions to pass file pointer around instead of struct and buffer (initially only for alias_byname())
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/libnss_ldapd@84 ef36b2f9-881f-0410-afb5-c4e39611909c
Diffstat (limited to 'server')
-rw-r--r-- | server/aliases.c | 38 | ||||
-rw-r--r-- | server/ldap-nss.c | 117 | ||||
-rw-r--r-- | server/ldap-nss.h | 12 | ||||
-rw-r--r-- | server/util.c | 72 | ||||
-rw-r--r-- | server/util.h | 4 |
5 files changed, 224 insertions, 19 deletions
diff --git a/server/aliases.c b/server/aliases.c index 248ddc8..d7031fd 100644 --- a/server/aliases.c +++ b/server/aliases.c @@ -42,8 +42,6 @@ #include "common.h" #include "log.h" -static struct ent_context *alias_context = NULL; - static enum nss_status _nss_ldap_parse_alias( LDAPMessage *e,struct ldap_state *pvt,void *result, char *buffer,size_t buflen) @@ -61,6 +59,19 @@ static enum nss_status _nss_ldap_parse_alias( return stat; } +static int write_alias(LDAPMessage *e,struct ldap_state *pvt,FILE *fp) +{ + int stat; + log_log(LOG_DEBUG,"write_alias: _nss_ldap_write_rndvalue"); + if ((stat=_nss_ldap_write_rndvalue(fp,e,ATM(LM_ALIASES,cn)))!=NSLCD_RESULT_SUCCESS) + return stat; + log_log(LOG_DEBUG,"write_alias: _nss_ldap_write_attrvals"); + if ((stat=_nss_ldap_write_attrvals(fp,e,AT(rfc822MailMember)))!=NSLCD_RESULT_SUCCESS) + return stat; + return NSLCD_RESULT_SUCCESS; +} + + /* macros for expanding the LDF_ALIAS macro */ #define LDF_STRING(field) WRITE_STRING(fp,field) #define LDF_STRINGLIST(field) WRITE_STRINGLIST_NUM(fp,field,result.alias_members_len) @@ -69,33 +80,23 @@ static enum nss_status _nss_ldap_parse_alias( int nslcd_alias_byname(FILE *fp) { - int32_t tmpint32,tmp2int32; + int32_t tmpint32; char *name; - /* these are here for now until we rewrite the LDAP code */ - struct aliasent result; - char buffer[1024]; - int errnop; - int retv; struct ldap_args a; /* read request parameters */ READ_STRING_ALLOC(fp,name); /* log call */ log_log(LOG_DEBUG,"nslcd_alias_byname(%s)",name); + /* write the response header */ + WRITE_INT32(fp,NSLCD_VERSION); + WRITE_INT32(fp,NSLCD_ACTION_ALIAS_BYNAME); /* do the LDAP request */ LA_INIT(a); LA_STRING(a)=name; LA_TYPE(a)=LA_TYPE_STRING; - retv=nss2nslcd(_nss_ldap_getbyname(&a,&result,buffer,1024,&errnop,_nss_ldap_filt_getaliasbyname,LM_ALIASES,_nss_ldap_parse_alias)); + _nss_ldap_searchbyname(&a,_nss_ldap_filt_getaliasbyname,LM_ALIASES,fp,write_alias); /* no more need for this */ free(name); - /* write the response */ - WRITE_INT32(fp,NSLCD_VERSION); - WRITE_INT32(fp,NSLCD_ACTION_ALIAS_BYNAME); - WRITE_INT32(fp,retv); - if (retv==NSLCD_RESULT_SUCCESS) - { - LDF_ALIAS; - } WRITE_FLUSH(fp); log_log(LOG_DEBUG,"nslcd_alias_byname DONE"); /* we're done */ @@ -105,6 +106,7 @@ int nslcd_alias_byname(FILE *fp) int nslcd_alias_all(FILE *fp) { int32_t tmpint32,tmp2int32; + static struct ent_context *alias_context; /* these are here for now until we rewrite the LDAP code */ struct aliasent result; char buffer[1024]; @@ -123,7 +125,7 @@ int nslcd_alias_all(FILE *fp) { /* write the result code */ WRITE_INT32(fp,retv); - /* write the password entry */ + /* write the alias entry */ LDF_ALIAS; fflush(fp); } diff --git a/server/ldap-nss.c b/server/ldap-nss.c index f5d4539..73b5a29 100644 --- a/server/ldap-nss.c +++ b/server/ldap-nss.c @@ -84,6 +84,9 @@ #include "util.h" #include "dnsconfig.h" #include "pagectrl.h" +#include "nslcd-server.h" +#include "common.h" +#include "log.h" #if defined(HAVE_THREAD_H) #ifdef HAVE_PTHREAD_ATFORK @@ -3207,6 +3210,94 @@ _nss_ldap_getbyname (struct ldap_args * args, return stat; } +static int NEW_do_parse_s(struct ent_context *ctx,FILE *fp,NEWparser_t parser) +{ + int parseStat=NSLCD_RESULT_NOTFOUND; + LDAPMessage *e=NULL; + /* + * if ec_state.ls_info.ls_index is non-zero, then we don't collect another + * entry off the LDAP chain, and instead refeed the existing result to + * the parser. Once the parser has finished with it, it will return + * NSS_STATUS_NOTFOUND and reset the index to -1, at which point we'll retrieve + * another entry. + */ + do + { + if (ctx->ec_state.ls_retry == 0 && + (ctx->ec_state.ls_type == LS_TYPE_KEY + || ctx->ec_state.ls_info.ls_index == -1)) + { + if (e == NULL) + e = ldap_first_entry (__session.ls_conn, ctx->ec_res); + else + e = ldap_next_entry (__session.ls_conn, e); + } + if (e == NULL) + { + /* Could not get a result; bail */ + parseStat=NSLCD_RESULT_NOTFOUND; + break; + } + /* + * We have an entry; now, try to parse it. + * + * If we do not parse the entry because of a schema + * violation, the parser should return NSS_STATUS_NOTFOUND. + * We'll keep on trying subsequent entries until we + * find one which is parseable, or exhaust avialable + * entries, whichever is first. + */ + parseStat=parser(e,&ctx->ec_state,fp); + /* hold onto the state if we're out of memory XXX */ + ctx->ec_state.ls_retry=0; + } + while (parseStat==NSLCD_RESULT_NOTFOUND); + return parseStat; +} + + +int _nss_ldap_searchbyname( + struct ldap_args *args,const char *filterprot, + enum ldap_map_selector sel,FILE *fp,NEWparser_t parser) +{ + int stat; + struct ent_context ctx; + int32_t tmpint32; + + _nss_ldap_enter(); + + ctx.ec_msgid=-1; + ctx.ec_cookie=NULL; + + stat=nss2nslcd(_nss_ldap_search_s(args,filterprot,sel,NULL,1,&ctx.ec_res)); + /* write the result code */ + WRITE_INT32(fp,stat); + /* bail on nothing found */ + if (stat!=NSLCD_RESULT_SUCCESS) + { + _nss_ldap_leave(); + return 1; + } + /* + * we pass this along for the benefit of the services parser, + * which uses it to figure out which protocol we really wanted. + * we only pass the second argument along, as that's what we need + * in services. + */ + LS_INIT(ctx.ec_state); + ctx.ec_state.ls_type=LS_TYPE_KEY; + ctx.ec_state.ls_info.ls_key=args->la_arg2.la_string; + /* call the parser for the result */ + stat=NEW_do_parse_s(&ctx,fp,parser); + + _nss_ldap_ent_context_release(&ctx); + + /* moved unlock here to avoid race condition bug #49 */ + _nss_ldap_leave(); + + return stat; +} + /* * These functions are called from within the parser, where it is assumed * to be safe to use the connection and the respective message. @@ -3308,6 +3399,32 @@ _nss_ldap_assign_attrvals (LDAPMessage * e, return NSS_STATUS_SUCCESS; } +int _nss_ldap_write_attrvals(FILE *fp,LDAPMessage *e,const char *attr) +{ + char **vals; + int valcount; + int i; + int32_t tmpint32; + /* log */ + log_log(LOG_DEBUG,"_nss_ldap_write_attrvals(%s)",attr); + /* check if we have a connection */ + if (__session.ls_conn==NULL) + return NSLCD_RESULT_UNAVAIL; + /* get the values and the number of values */ + vals=ldap_get_values(__session.ls_conn,e,(char *)attr); + valcount=(vals==NULL)?0:ldap_count_values(vals); + /* write number of entries */ + WRITE_INT32(fp,valcount); + /* write the entries themselves */ + for (i=0;i<valcount;i++) + { + WRITE_STRING(fp,vals[i]); + } + if (vals!=NULL) + ldap_value_free(vals); + return NSLCD_RESULT_SUCCESS; +} + /* Assign a single value to *valptr. */ enum nss_status _nss_ldap_assign_attrval (LDAPMessage * e, diff --git a/server/ldap-nss.h b/server/ldap-nss.h index 684354b..02963a1 100644 --- a/server/ldap-nss.h +++ b/server/ldap-nss.h @@ -499,6 +499,10 @@ struct name_list typedef enum nss_status (*parser_t) (LDAPMessage *, struct ldap_state *, void *, char *, size_t); + +typedef int (*NEWparser_t)(LDAPMessage *e,struct ldap_state *pvt,FILE *fp); + + /* * Portable locking macro. */ @@ -619,6 +623,12 @@ enum nss_status _nss_ldap_getbyname (struct ldap_args * args, /* IN/OUT * enum ldap_map_selector sel, /* IN */ parser_t parser /* IN */ ); +int _nss_ldap_searchbyname(struct ldap_args *args, /* IN/OUT */ + const char *filterprot, /* IN */ + enum ldap_map_selector sel, /* IN */ + FILE *fp,NEWparser_t parser /* IN */ ); + + /* parsing utility functions */ enum nss_status _nss_ldap_assign_attrvals (LDAPMessage * e, /* IN */ const char *attr, /* IN */ @@ -628,6 +638,8 @@ enum nss_status _nss_ldap_assign_attrvals (LDAPMessage * e, /* IN */ size_t * buflen, /* IN/OUT */ size_t * pvalcount /* OUT */ ); +int _nss_ldap_write_attrvals(FILE *fp,LDAPMessage *e,const char *attr); + enum nss_status _nss_ldap_assign_attrval (LDAPMessage * e, /* IN */ const char *attr, /* IN */ char **valptr, /* OUT */ diff --git a/server/util.c b/server/util.c index 786d0a8..e2888f6 100644 --- a/server/util.c +++ b/server/util.c @@ -50,6 +50,9 @@ #include "ldap-nss.h" #include "util.h" +#include "nslcd-server.h" +#include "common.h" +#include "log.h" static enum nss_status do_getrdnvalue (const char *dn, const char *rdntype, @@ -249,6 +252,75 @@ _nss_ldap_getrdnvalue (LDAPMessage * entry, return status; } +int _nss_ldap_write_rndvalue(FILE *fp,LDAPMessage *entry,const char *rdntype) +{ + char *dn; + int status=456; + char **vals; + int32_t tmpint32; + char **exploded_dn; + char **exploded_rdn; + char rdnava[64]; + int rdnavalen; + int i; + /* log call */ + log_log(LOG_DEBUG,"_nss_ldap_write_rndvalue(%s)",rdntype); + /* get the dn from the entry */ + dn=_nss_ldap_get_dn(entry); + if (dn==NULL) + return NSLCD_RESULT_NOTFOUND; + /* append a `=' to the rdntype */ + snprintf(rdnava,sizeof(rdnava),"%s=",rdntype); + rdnavalen=strlen(rdnava); + /* explode dn */ + exploded_dn=ldap_explode_dn(dn,0); + if (exploded_dn!=NULL) + { + /* + * attempt to get the naming attribute's principal + * value by parsing the RDN. We need to support + * multivalued RDNs (as they're essentially mandated + * for services) + */ + exploded_rdn=ldap_explode_rdn(exploded_dn[0],0); + if (exploded_rdn!=NULL) + { + for (i=0;exploded_rdn[i]!=NULL;i++) + { + /* if the values begins with rndava */ + if (strncasecmp(exploded_rdn[i],rdnava,rdnavalen)==0) + { + /* FIXME: handle case where WRITE fails */ + WRITE_STRING(fp,exploded_rdn[i]+rdnavalen); + status=0; + break; + } + } + ldap_value_free(exploded_rdn); + } + ldap_value_free(exploded_dn); + } + ldap_memfree(dn); + /* + * If examining the DN failed, then pick the nominal first + * value of cn as the canonical name (recall that attributes + * are sets, not sequences) + */ + if (status==456) + { + vals=_nss_ldap_get_values(entry,rdntype); + if (vals!=NULL) + { + /* write the first entry */ + WRITE_STRING(fp,vals[0]); + status=NSS_STATUS_SUCCESS; + ldap_value_free(vals); + status=0; + } + } + return status; +} + static enum nss_status do_getrdnvalue (const char *dn, const char *rdntype, diff --git a/server/util.h b/server/util.h index ea0d57f..1a90b52 100644 --- a/server/util.h +++ b/server/util.h @@ -36,10 +36,12 @@ * get the RDN's value: eg. if the RDN was cn=lukeh, getrdnvalue(entry) * would return lukeh. */ -enum nss_status _nss_ldap_getrdnvalue (LDAPMessage * entry, +enum nss_status _nss_ldap_getrdnvalue(LDAPMessage *entry, const char *rdntype, char **rval, char **buf, size_t * len); +int _nss_ldap_write_rndvalue(FILE *fp,LDAPMessage *entry,const char *rdntype); + /* * map a distinguished name to a login name, or group entry */ |