Back to index

openldap  2.4.31
shadow.c
Go to the documentation of this file.
00001 /* shadow.c - shadow account lookup routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 
00004  *
00005  * Copyright 2008-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2008 by Howard Chu, Symas Corp.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This code references portions of the nss-ldapd package
00019  * written by Arthur de Jong. The nss-ldapd code was forked
00020  * from the nss-ldap library written by Luke Howard.
00021  */
00022 
00023 #include "nssov.h"
00024 
00025 /* ( nisSchema.2.1 NAME 'shadowAccount' SUP top AUXILIARY
00026  *      DESC 'Additional attributes for shadow passwords'
00027  *      MUST uid
00028  *      MAY ( userPassword $ shadowLastChange $ shadowMin
00029  *                           shadowMax $ shadowWarning $ shadowInactive $
00030  *                           shadowExpire $ shadowFlag $ description ) )
00031  */
00032 
00033 /* the basic search filter for searches */
00034 static struct berval shadow_filter = BER_BVC("(objectClass=shadowAccount)");
00035 
00036 /* the attributes to request with searches */
00037 static struct berval shadow_keys[] = {
00038        BER_BVC("uid"),
00039        BER_BVC("userPassword"),
00040        BER_BVC("shadowLastChange"),
00041        BER_BVC("shadowMin"),
00042        BER_BVC("shadowMax"),
00043        BER_BVC("shadowWarning"),
00044        BER_BVC("shadowInactive"),
00045        BER_BVC("shadowExpire"),
00046        BER_BVC("shadowFlag"),
00047        BER_BVNULL
00048 };
00049 
00050 #define UID_KEY      0
00051 #define PWD_KEY      1
00052 #define CHG_KEY      2
00053 #define MIN_KEY      3
00054 #define MAX_KEY 4
00055 #define WRN_KEY 5
00056 #define INA_KEY 6
00057 #define EXP_KEY 7
00058 #define FLG_KEY 8
00059 
00060 /* default values for attributes */
00061 static struct berval default_shadow_userPassword         = BER_BVC("*"); /* unmatchable */
00062 static int default_nums[] = { 0,0,
00063        -1, /* LastChange */
00064        -1, /* Min */
00065        -1, /* Max */
00066        -1, /* Warning */
00067        -1, /* Inactive */
00068        -1, /* Expire */
00069        0 /* Flag */
00070 };
00071 
00072 NSSOV_INIT(shadow)
00073 
00074 static long to_date(struct berval *date,AttributeDescription *attr)
00075 {
00076        long value;
00077        char *tmp;
00078        /* do some special handling for date values on AD */
00079        if (strcasecmp(attr->ad_cname.bv_val,"pwdLastSet")==0)
00080        {
00081               char buffer[8];
00082               size_t l;
00083               /* we expect an AD 64-bit datetime value;
00084                       we should do date=date/864000000000-134774
00085                       but that causes problems on 32-bit platforms,
00086                       first we devide by 1000000000 by stripping the
00087                       last 9 digits from the string and going from there */
00088               l=date->bv_len-9;
00089               if (l<1 || l>(sizeof(buffer)-1))
00090                      return 0; /* error */
00091               strncpy(buffer,date->bv_val,l);
00092               buffer[l]='\0';
00093               value=strtol(buffer,&tmp,0);
00094               if ((buffer[0]=='\0')||(*tmp!='\0'))
00095               {
00096                      Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
00097                             attr->ad_cname.bv_val,0,0);
00098                      return 0;
00099               }
00100               return value/864-134774;
00101               /* note that AD does not have expiry dates but a lastchangeddate
00102                       and some value that needs to be added */
00103        }
00104        value=strtol(date->bv_val,&tmp,0);
00105        if ((date->bv_val[0]=='\0')||(*tmp!='\0'))
00106        {
00107               Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
00108                      attr->ad_cname.bv_val,0,0);
00109               return 0;
00110        }
00111        return value;
00112 }
00113 
00114 #ifndef UF_DONT_EXPIRE_PASSWD
00115 #define UF_DONT_EXPIRE_PASSWD 0x10000
00116 #endif
00117 
00118 #define GET_OPTIONAL_LONG(var,key) \
00119        a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
00120        if ( !a || BER_BVISNULL(&a->a_vals[0])) \
00121               var = default_nums[key]; \
00122        else \
00123        { \
00124               if (a->a_numvals > 1) \
00125               { \
00126                      Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
00127                             entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
00128               } \
00129               var=strtol(a->a_vals[0].bv_val,&tmp,0); \
00130               if ((a->a_vals[0].bv_val[0]=='\0')||(*tmp!='\0')) \
00131               { \
00132                      Debug(LDAP_DEBUG_ANY,"shadow entry %s contains non-numeric %s value\n", \
00133                             entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
00134                      return 0; \
00135               } \
00136        }
00137 
00138 #define GET_OPTIONAL_DATE(var,key) \
00139        a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
00140        if ( !a || BER_BVISNULL(&a->a_vals[0])) \
00141               var = default_nums[key]; \
00142        else \
00143        { \
00144               if (a->a_numvals > 1) \
00145               { \
00146                      Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
00147                             entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
00148               } \
00149               var=to_date(&a->a_vals[0],cbp->mi->mi_attrs[key].an_desc); \
00150        }
00151 
00152 NSSOV_CBPRIV(shadow,
00153        char buf[256];
00154        struct berval name;);
00155 
00156 static int write_shadow(nssov_shadow_cbp *cbp,Entry *entry)
00157 {
00158        struct berval tmparr[2];
00159        struct berval *names;
00160        Attribute *a;
00161        char *tmp;
00162        struct berval passwd = {0};
00163        long lastchangedate;
00164        long mindays;
00165        long maxdays;
00166        long warndays;
00167        long inactdays;
00168        long expiredate;
00169        unsigned long flag;
00170        int i;
00171        int32_t tmpint32;
00172        /* get username */
00173        if (BER_BVISNULL(&cbp->name))
00174        {
00175               a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[UID_KEY].an_desc);
00176               if (!a)
00177               {
00178                      Debug(LDAP_DEBUG_ANY,"shadow entry %s does not contain %s value\n",
00179                             entry->e_name.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val,0);
00180                      return 0;
00181               }
00182               names = a->a_vals;
00183        }
00184        else
00185        {
00186               names=tmparr;
00187               names[0]=cbp->name;
00188               BER_BVZERO(&names[1]);
00189        }
00190        /* get password */
00191        a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);
00192        if ( a )
00193               get_userpassword(&a->a_vals[0], &passwd);
00194        if (BER_BVISNULL(&passwd))
00195               passwd=default_shadow_userPassword;
00196        /* get lastchange date */
00197        GET_OPTIONAL_DATE(lastchangedate,CHG_KEY);
00198        /* get mindays */
00199        GET_OPTIONAL_LONG(mindays,MIN_KEY);
00200        /* get maxdays */
00201        GET_OPTIONAL_LONG(maxdays,MAX_KEY);
00202        /* get warndays */
00203        GET_OPTIONAL_LONG(warndays,WRN_KEY);
00204        /* get inactdays */
00205        GET_OPTIONAL_LONG(inactdays,INA_KEY);
00206        /* get expire date */
00207        GET_OPTIONAL_LONG(expiredate,EXP_KEY);
00208        /* get flag */
00209        GET_OPTIONAL_LONG(flag,FLG_KEY);
00210        /* if we're using AD handle the flag specially */
00211        if (strcasecmp(cbp->mi->mi_attrs[CHG_KEY].an_desc->ad_cname.bv_val,"pwdLastSet")==0)
00212        {
00213               if (flag&UF_DONT_EXPIRE_PASSWD)
00214                      maxdays=99999;
00215               flag=0;
00216        }
00217        /* write the entries */
00218        for (i=0;!BER_BVISNULL(&names[i]);i++)
00219        {
00220               WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
00221               WRITE_BERVAL(cbp->fp,&names[i]);
00222               WRITE_BERVAL(cbp->fp,&passwd);
00223               WRITE_INT32(cbp->fp,lastchangedate);
00224               WRITE_INT32(cbp->fp,mindays);
00225               WRITE_INT32(cbp->fp,maxdays);
00226               WRITE_INT32(cbp->fp,warndays);
00227               WRITE_INT32(cbp->fp,inactdays);
00228               WRITE_INT32(cbp->fp,expiredate);
00229               WRITE_INT32(cbp->fp,flag);
00230        }
00231        return 0;
00232 }
00233 
00234 NSSOV_CB(shadow)
00235 
00236 NSSOV_HANDLE(
00237        shadow,byname,
00238        char fbuf[1024];
00239        struct berval filter = {sizeof(fbuf)};
00240        filter.bv_val = fbuf;
00241        READ_STRING(fp,cbp.buf);,
00242        cbp.name.bv_len = tmpint32;
00243        cbp.name.bv_val = cbp.buf;
00244        Debug(LDAP_DEBUG_ANY,"nssov_shadow_byname(%s)\n",cbp.name.bv_val,0,0);,
00245        NSLCD_ACTION_SHADOW_BYNAME,
00246        nssov_filter_byname(cbp.mi,UID_KEY,&cbp.name,&filter)
00247 )
00248 
00249 NSSOV_HANDLE(
00250        shadow,all,
00251        struct berval filter;
00252        /* no parameters to read */
00253        BER_BVZERO(&cbp.name);,
00254        Debug(LDAP_DEBUG_ANY,"nssov_shadow_all()\n",0,0,0);,
00255        NSLCD_ACTION_SHADOW_ALL,
00256        (filter=cbp.mi->mi_filter,0)
00257 )