summaryrefslogtreecommitdiffstats
path: root/contrib/slapd-modules/nssov/shadow.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/slapd-modules/nssov/shadow.c')
-rw-r--r--contrib/slapd-modules/nssov/shadow.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/contrib/slapd-modules/nssov/shadow.c b/contrib/slapd-modules/nssov/shadow.c
new file mode 100644
index 0000000..477ce50
--- /dev/null
+++ b/contrib/slapd-modules/nssov/shadow.c
@@ -0,0 +1,257 @@
+/* shadow.c - shadow account lookup routines */
+/* $OpenLDAP$ */
+/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
+ *
+ * Copyright 2008-2022 The OpenLDAP Foundation.
+ * Portions Copyright 2008 by Howard Chu, Symas Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License.
+ *
+ * A copy of this license is available in the file LICENSE in the
+ * top-level directory of the distribution or, alternatively, at
+ * <http://www.OpenLDAP.org/license.html>.
+ */
+/* ACKNOWLEDGEMENTS:
+ * This code references portions of the nss-ldapd package
+ * written by Arthur de Jong. The nss-ldapd code was forked
+ * from the nss-ldap library written by Luke Howard.
+ */
+
+#include "nssov.h"
+
+/* ( nisSchema.2.1 NAME 'shadowAccount' SUP top AUXILIARY
+ * DESC 'Additional attributes for shadow passwords'
+ * MUST uid
+ * MAY ( userPassword $ shadowLastChange $ shadowMin
+ * shadowMax $ shadowWarning $ shadowInactive $
+ * shadowExpire $ shadowFlag $ description ) )
+ */
+
+/* the basic search filter for searches */
+static struct berval shadow_filter = BER_BVC("(objectClass=shadowAccount)");
+
+/* the attributes to request with searches */
+static struct berval shadow_keys[] = {
+ BER_BVC("uid"),
+ BER_BVC("userPassword"),
+ BER_BVC("shadowLastChange"),
+ BER_BVC("shadowMin"),
+ BER_BVC("shadowMax"),
+ BER_BVC("shadowWarning"),
+ BER_BVC("shadowInactive"),
+ BER_BVC("shadowExpire"),
+ BER_BVC("shadowFlag"),
+ BER_BVNULL
+};
+
+#define UID_KEY 0
+#define PWD_KEY 1
+#define CHG_KEY 2
+#define MIN_KEY 3
+#define MAX_KEY 4
+#define WRN_KEY 5
+#define INA_KEY 6
+#define EXP_KEY 7
+#define FLG_KEY 8
+
+/* default values for attributes */
+static struct berval default_shadow_userPassword = BER_BVC("*"); /* unmatchable */
+static int default_nums[] = { 0,0,
+ -1, /* LastChange */
+ -1, /* Min */
+ -1, /* Max */
+ -1, /* Warning */
+ -1, /* Inactive */
+ -1, /* Expire */
+ 0 /* Flag */
+};
+
+NSSOV_INIT(shadow)
+
+static long to_date(struct berval *date,AttributeDescription *attr)
+{
+ long value;
+ char *tmp;
+ /* do some special handling for date values on AD */
+ if (strcasecmp(attr->ad_cname.bv_val,"pwdLastSet")==0)
+ {
+ char buffer[8];
+ size_t l;
+ /* we expect an AD 64-bit datetime value;
+ we should do date=date/864000000000-134774
+ but that causes problems on 32-bit platforms,
+ first we divide by 1000000000 by stripping the
+ last 9 digits from the string and going from there */
+ l=date->bv_len-9;
+ if (l<1 || l>(sizeof(buffer)-1))
+ return 0; /* error */
+ strncpy(buffer,date->bv_val,l);
+ buffer[l]='\0';
+ value=strtol(buffer,&tmp,0);
+ if ((buffer[0]=='\0')||(*tmp!='\0'))
+ {
+ Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
+ attr->ad_cname.bv_val );
+ return 0;
+ }
+ return value/864-134774;
+ /* note that AD does not have expiry dates but a lastchangeddate
+ and some value that needs to be added */
+ }
+ value=strtol(date->bv_val,&tmp,0);
+ if ((date->bv_val[0]=='\0')||(*tmp!='\0'))
+ {
+ Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
+ attr->ad_cname.bv_val );
+ return 0;
+ }
+ return value;
+}
+
+#ifndef UF_DONT_EXPIRE_PASSWD
+#define UF_DONT_EXPIRE_PASSWD 0x10000
+#endif
+
+#define GET_OPTIONAL_LONG(var,key) \
+ a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
+ if ( !a || BER_BVISNULL(&a->a_vals[0])) \
+ var = default_nums[key]; \
+ else \
+ { \
+ if (a->a_numvals > 1) \
+ { \
+ Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
+ entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val); \
+ } \
+ var=strtol(a->a_vals[0].bv_val,&tmp,0); \
+ if ((a->a_vals[0].bv_val[0]=='\0')||(*tmp!='\0')) \
+ { \
+ Debug(LDAP_DEBUG_ANY,"shadow entry %s contains non-numeric %s value\n", \
+ entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val); \
+ return 0; \
+ } \
+ }
+
+#define GET_OPTIONAL_DATE(var,key) \
+ a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
+ if ( !a || BER_BVISNULL(&a->a_vals[0])) \
+ var = default_nums[key]; \
+ else \
+ { \
+ if (a->a_numvals > 1) \
+ { \
+ Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
+ entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val); \
+ } \
+ var=to_date(&a->a_vals[0],cbp->mi->mi_attrs[key].an_desc); \
+ }
+
+NSSOV_CBPRIV(shadow,
+ char buf[256];
+ struct berval name;);
+
+static int write_shadow(nssov_shadow_cbp *cbp,Entry *entry)
+{
+ struct berval tmparr[2];
+ struct berval *names;
+ Attribute *a;
+ char *tmp;
+ struct berval passwd = {0};
+ long lastchangedate;
+ long mindays;
+ long maxdays;
+ long warndays;
+ long inactdays;
+ long expiredate;
+ unsigned long flag;
+ int i;
+ int32_t tmpint32;
+ /* get username */
+ if (BER_BVISNULL(&cbp->name))
+ {
+ a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[UID_KEY].an_desc);
+ if (!a)
+ {
+ Debug(LDAP_DEBUG_ANY,"shadow entry %s does not contain %s value\n",
+ entry->e_name.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val );
+ return 0;
+ }
+ names = a->a_vals;
+ }
+ else
+ {
+ names=tmparr;
+ names[0]=cbp->name;
+ BER_BVZERO(&names[1]);
+ }
+ /* get password */
+ a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);
+ if ( a )
+ get_userpassword(&a->a_vals[0], &passwd);
+ if (BER_BVISNULL(&passwd))
+ passwd=default_shadow_userPassword;
+ /* get lastchange date */
+ GET_OPTIONAL_DATE(lastchangedate,CHG_KEY);
+ /* get mindays */
+ GET_OPTIONAL_LONG(mindays,MIN_KEY);
+ /* get maxdays */
+ GET_OPTIONAL_LONG(maxdays,MAX_KEY);
+ /* get warndays */
+ GET_OPTIONAL_LONG(warndays,WRN_KEY);
+ /* get inactdays */
+ GET_OPTIONAL_LONG(inactdays,INA_KEY);
+ /* get expire date */
+ GET_OPTIONAL_LONG(expiredate,EXP_KEY);
+ /* get flag */
+ GET_OPTIONAL_LONG(flag,FLG_KEY);
+ /* if we're using AD handle the flag specially */
+ if (strcasecmp(cbp->mi->mi_attrs[CHG_KEY].an_desc->ad_cname.bv_val,"pwdLastSet")==0)
+ {
+ if (flag&UF_DONT_EXPIRE_PASSWD)
+ maxdays=99999;
+ flag=0;
+ }
+ /* write the entries */
+ for (i=0;!BER_BVISNULL(&names[i]);i++)
+ {
+ WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
+ WRITE_BERVAL(cbp->fp,&names[i]);
+ WRITE_BERVAL(cbp->fp,&passwd);
+ WRITE_INT32(cbp->fp,lastchangedate);
+ WRITE_INT32(cbp->fp,mindays);
+ WRITE_INT32(cbp->fp,maxdays);
+ WRITE_INT32(cbp->fp,warndays);
+ WRITE_INT32(cbp->fp,inactdays);
+ WRITE_INT32(cbp->fp,expiredate);
+ WRITE_INT32(cbp->fp,flag);
+ }
+ return 0;
+}
+
+NSSOV_CB(shadow)
+
+NSSOV_HANDLE(
+ shadow,byname,
+ char fbuf[1024];
+ struct berval filter = {sizeof(fbuf)};
+ filter.bv_val = fbuf;
+ READ_STRING(fp,cbp.buf);,
+ cbp.name.bv_len = tmpint32;
+ cbp.name.bv_val = cbp.buf;
+ Debug(LDAP_DEBUG_ANY,"nssov_shadow_byname(%s)\n",cbp.name.bv_val);,
+ NSLCD_ACTION_SHADOW_BYNAME,
+ nssov_filter_byname(cbp.mi,UID_KEY,&cbp.name,&filter)
+)
+
+NSSOV_HANDLE(
+ shadow,all,
+ struct berval filter;
+ /* no parameters to read */
+ BER_BVZERO(&cbp.name);,
+ Debug(LDAP_DEBUG_ANY,"nssov_shadow_all()\n");,
+ NSLCD_ACTION_SHADOW_ALL,
+ (filter=cbp.mi->mi_filter,0)
+)