shadow.c 6.85 KB
Newer Older
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
1
2
/* shadow.c - shadow account lookup routines */
/* $OpenLDAP$ */
3
4
/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 
 *
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
5
 * Copyright 2008-2018 The OpenLDAP Foundation.
6
 * Portions Copyright 2008 by Howard Chu, Symas Corp.
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
7
8
9
10
11
12
13
14
15
16
 * 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>.
 */
17
/* ACKNOWLEDGEMENTS:
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
 * 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 devide 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'))
		{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
96
			Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
97
98
99
100
101
102
103
104
105
106
				attr->ad_cname.bv_val,0,0);
			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'))
	{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
107
		Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
			attr->ad_cname.bv_val,0,0);
		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) \
		{ \
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
126
			Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
127
128
129
130
131
				entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
		} \
		var=strtol(a->a_vals[0].bv_val,&tmp,0); \
		if ((a->a_vals[0].bv_val[0]=='\0')||(*tmp!='\0')) \
		{ \
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
132
			Debug(LDAP_DEBUG_ANY,"shadow entry %s contains non-numeric %s value\n", \
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
133
134
135
136
137
138
139
140
141
142
143
144
145
				entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
			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) \
		{ \
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
146
			Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
				entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
		} \
		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)
		{
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
178
			Debug(LDAP_DEBUG_ANY,"shadow entry %s does not contain %s value\n",
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
				entry->e_name.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val,0);
			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++)
	{
220
		WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
		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;
241
	READ_STRING(fp,cbp.buf);,
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
242
243
	cbp.name.bv_len = tmpint32;
	cbp.name.bv_val = cbp.buf;
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
244
	Debug(LDAP_DEBUG_ANY,"nssov_shadow_byname(%s)\n",cbp.name.bv_val,0,0);,
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
245
246
247
248
249
250
251
252
253
	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);,
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
254
	Debug(LDAP_DEBUG_ANY,"nssov_shadow_all()\n",0,0,0);,
Quanah Gibson-Mount's avatar
Quanah Gibson-Mount committed
255
256
257
	NSLCD_ACTION_SHADOW_ALL,
	(filter=cbp.mi->mi_filter,0)
)