Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2006-11-11 15:02:25 +0100
committerArthur de Jong <arthur@arthurdejong.org>2006-11-11 15:02:25 +0100
commitdb14b113e055fa7ab006cfe1c04961bba19a85de (patch)
tree4ffec7243dd1c56f3fdfddbe294e7451c408f384 /server
parentbffd85ce667130419ddb381421e1a524f490b981 (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.c38
-rw-r--r--server/ldap-nss.c117
-rw-r--r--server/ldap-nss.h12
-rw-r--r--server/util.c72
-rw-r--r--server/util.h4
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
*/