1 /*
2  * Copyright (C) 1998-2004 Luke Howard.
3  * This file is part of the pam_ldap library.
4  * Contributed by Luke Howard, <lukeh@padl.com>, 1998.
5  *
6  * The pam_ldap library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * The pam_ldap library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with the pam_ldap library; see the file COPYING.LIB.  If not,
18  * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
22 #ifdef HAVE_SECURITY_PAM_APPL_H
23 #include <security/pam_appl.h>
24 #elif defined(HAVE_PAM_PAM_APPL_H)
25 #include <pam/pam_appl.h>
26 #endif
27 
28 #ifdef HAVE_SECURITY_PAM_MISC_H
29 #include <security/pam_misc.h>
30 #elif defined(HAVE_PAM_PAM_MISC_H)
31 #include <pam/pam_misc.h>
32 #endif
33 
34 #ifndef HAVE_PAM_PAM_MODULES_H
35 #include <security/pam_modules.h>
36 #else
37 #include <pam/pam_modules.h>
38 #endif
39 
40 typedef struct pam_ssd
41   {
42     char *base;
43     int scope;
44     char *filter;
45     struct pam_ssd *next;
46 } pam_ssd_t;
47 
48 /* /etc/ldap.conf nss_ldap-style configuration */
49 typedef struct pam_ldap_config
50   {
51     /* file name read from */
52     char *configFile;
53     /* URI */
54     char *uri;
55     /* space delimited list of servers */
56     char *host;
57     /* port, expected to be common to all servers */
58     int port;
59     /* base DN, eg. dc=gnu,dc=org */
60     char *base;
61     /* scope for searches */
62     int scope;
63     /* deref policy */
64     int deref;
65     /* bind dn/pw for "anonymous" authentication */
66     char *binddn;
67     char *bindpw;
68     /* bind dn/pw for "root" authentication */
69     char *rootbinddn;
70     char *rootbindpw;
71     /* SSL config states */
72 #define SSL_OFF          0
73 #define SSL_LDAPS        1
74 #define SSL_START_TLS    2
75     int ssl_on;
76     /* SSL path */
77     char *sslpath;
78     /* list of SSDs to augment defaults */
79     pam_ssd_t *ssd;
80     /* filter to AND with uid=%s */
81     char *filter;
82     /* attribute to search on; defaults to uid. Use CN with ADS? */
83     char *userattr;
84     /* attribute to set PAM_USER based on */
85     char *tmplattr;
86     /* default template user */
87     char *tmpluser;
88     /* search for Netscape password policy */
89     int getpolicy;
90     /* host attribute checking, for access authorization */
91     int checkhostattr;
92     /* service attribute checking, for access authorization */
93     int checkserviceattr;
94     /* group name; optional, for access authorization */
95     char *groupdn;
96     /* group membership attribute; defaults to uniquemember */
97     char *groupattr;
98     /* LDAP protocol version */
99     int version;
100     /* search timelimit */
101     int timelimit;
102     /* bind timelimit */
103     int bind_timelimit;
104     /* automatically chase referrals */
105     int referrals;
106     /* restart interrupted syscalls, OpenLDAP only */
107     int restart;
108     /* chauthtok config states */
109 #define PASSWORD_CLEAR   0
110 #define PASSWORD_CRYPT   1
111 #define PASSWORD_MD5     2
112 #define PASSWORD_CLEAR_REMOVE_OLD     3
113 #define PASSWORD_AD      4
114 #define PASSWORD_EXOP    5
115 #define PASSWORD_EXOP_SEND_OLD	6
116     int password_type;
117     /* stop all changes, present message */
118     char *password_prohibit_message;
119     /* min uid */
120     uid_t min_uid;
121     /* max uid */
122     uid_t max_uid;
123     /* tls check peer */
124     int tls_checkpeer;
125     /* tls ca certificate file */
126     char *tls_cacertfile;
127     /* tls ca certificate dir */
128     char *tls_cacertdir;
129     /* tls ciphersuite */
130     char *tls_ciphers;
131     /* tls certificate */
132     char *tls_cert;
133     /* tls key */
134     char *tls_key;
135     /* tls randfile */
136     char *tls_randfile;
137     /* directory for debug files */
138     char *logdir;
139     /* ldap debug level */
140     int debug;
141     /* SASL mechanism */
142     char *sasl_mechanism;
143   }
144 pam_ldap_config_t;
145 
146 /* Netscape global password policy attributes */
147 typedef struct pam_ldap_password_policy
148   {
149     int password_change;
150     int password_check_syntax;
151     int password_min_length;
152     int password_exp;
153     int password_max_age;
154     int password_warning;
155     int password_keep_history;
156     int password_in_history;
157     int password_lockout;
158     int password_max_failure;
159     int password_unlock;
160     int password_lockout_duration;
161     int password_reset_duration;
162   }
163 pam_ldap_password_policy_t;
164 
165 /* Standard Unix style shadow controls */
166 typedef struct pam_ldap_shadow
167   {
168     int shadowacct;		/* is shadowAccount */
169     long int lstchg;		/* Date of last change.  */
170     long int min;		/* Minimum number of days between changes.  */
171     long int max;		/* Maximum number of days between changes.  */
172     long int warn;		/* Number of days to warn user to change
173 				   the password.  */
174     long int inact;		/* Number of days the account may be
175 				   inactive.  */
176     long int expire;		/* Number of days since 1970-01-01 until
177 				   account expires.  */
178     long int flag;	        /* Reserved.  */
179   }
180 pam_ldap_shadow_t;
181 
182 /* Password controls sent to client */
183 #ifndef LDAP_CONTROL_PWEXPIRED
184 #define LDAP_CONTROL_PWEXPIRED      "2.16.840.1.113730.3.4.4"
185 #endif /* LDAP_CONTROL_PWEXPIRED */
186 #ifndef LDAP_CONTROL_PWEXPIRING
187 #define LDAP_CONTROL_PWEXPIRING     "2.16.840.1.113730.3.4.5"
188 #endif /* LDAP_CONTROL_PWEXPIRING */
189 #ifndef LDAP_CONTROL_PASSWORDPOLICYREQUEST
190 #define LDAP_CONTROL_PASSWORDPOLICYREQUEST	"1.3.6.1.4.1.42.2.27.8.5.1"
191 #endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */
192 #ifndef LDAP_CONTROL_PASSWORDPOLICYRESPONSE
193 #define LDAP_CONTROL_PASSWORDPOLICYRESPONSE	"1.3.6.1.4.1.42.2.27.8.5.1"
194 #endif	/* LDAP_CONTROL_PASSWORDPOLICYRESPONSE */
195 
196 #define POLICY_WARN_TIME_BEFORE_EXPIRATION		128
197 #define POLICY_WARN_GRACE_LOGINS_REMAINING		129
198 
199 #define POLICY_ERROR_SUCCESS				-1
200 #define POLICY_ERROR_PASSWORD_EXPIRED			0
201 #define POLICY_ERROR_ACCOUNT_LOCKED			1
202 #define POLICY_ERROR_CHANGE_AFTER_RESET			2
203 #define POLICY_ERROR_PASSWORD_MOD_NOT_ALLOWED		3
204 #define POLICY_ERROR_MUST_SUPPLY_OLD_PASSWORD		4
205 #define POLICY_ERROR_INSUFFICIENT_PASSWORD_QUALITY	5
206 #define POLICY_ERROR_PASSWORD_TOO_SHORT			6
207 #define POLICY_ERROR_PASSWORD_TOO_YOUNG			7
208 #define POLICY_ERROR_PASSWORD_INSUFFICIENT		8
209 
210 #ifndef LDAP_OPT_ON
211 #define LDAP_OPT_ON ((void *) 1)
212 #endif /* LDAP_OPT_ON */
213 #ifndef LDAP_OPT_OFF
214 #define LDAP_OPT_OFF ((void *) 0)
215 #endif /* LDAP_OPT_OFF */
216 
217 #if defined(LDAP_EXOP_X_MODIFY_PASSWD) && !defined(LDAP_EXOP_MODIFY_PASSWD)
218 #define LDAP_EXOP_MODIFY_PASSWD LDAP_EXOP_X_MODIFY_PASSWD
219 #define LDAP_TAG_EXOP_MODIFY_PASSWD_ID LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID
220 #define LDAP_TAG_EXOP_MODIFY_PASSWD_OLD LDAP_TAG_EXOP_X_MODIFY_PASSWD_OLD
221 #define LDAP_TAG_EXOP_MODIFY_PASSWD_NEW LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW
222 #endif
223 
224 /* Seconds in a day */
225 #define SECSPERDAY 86400
226 
227 /* Netscape per-use password attributes. Unused except for DN. */
228 typedef struct pam_ldap_user_info
229   {
230     /* user name, to validate info cache */
231     char *username;
232     /* DN of user in directory */
233     char *userdn;
234     /* temporary cache of user's bind credentials for rebind function */
235     char *userpw;
236     /* host attribute from account objectclass */
237     char **hosts_allow;
238     char **services_allow;
239     /* seconds until password expires */
240     long password_expiration_time;
241     /* grace logins remaining */
242     int grace_logins_remaining;
243     /* password policy error */
244     int policy_error;
245     /* bound as user DN */
246     int bound_as_user;
247     /* user ID */
248     uid_t uid;
249     /* mapped user */
250     char *tmpluser;
251     /* shadow stuff */
252     pam_ldap_shadow_t shadow;
253   }
254 pam_ldap_user_info_t;
255 
256 /*
257  * Per PAM-call LDAP session. We keep the user info and
258  * LDAP handle cached to minimize binds and searches to
259  * the directory, particularly as you can't rebind within
260  * a V2 session.
261  */
262 typedef struct pam_ldap_session
263   {
264     LDAP *ld;
265     pam_ldap_config_t *conf;
266     pam_ldap_user_info_t *info;
267   }
268 pam_ldap_session_t;
269 
270 #define OLD_PASSWORD_PROMPT "Enter login(LDAP) password: "
271 #define NEW_PASSWORD_PROMPT "New password: "
272 #define AGAIN_PASSWORD_PROMPT "Re-enter new password: "
273 
274 /* pam_ldap session */
275 #define PADL_LDAP_SESSION_DATA "PADL-LDAP-SESSION-DATA"
276 /* expired user */
277 #define PADL_LDAP_AUTHTOK_DATA "PADL-LDAP-AUTHTOK-DATA"
278 /* non-template user (pre-mapping) */
279 #define PADL_LDAP_AUTH_DATA "PADL-LDAP-AUTH-DATA"
280 /* authtok for Solaris */
281 #define PADL_LDAP_OLDAUTHTOK_DATA "PADL-LDAP-OLDAUTHTOK-DATA"
282 
283 #ifndef PAM_EXTERN
284 #define PAM_EXTERN
285 #endif
286 
287 #ifndef _pam_overwrite
288 #define _pam_overwrite(x) \
289 { \
290      register char *__xx__; \
291      if ((__xx__=x)) \
292           while (*__xx__) \
293                *__xx__++ = '\0'; \
294 }
295 #endif
296 
297 #ifndef _pam_drop
298 #define _pam_drop(X) \
299 if (X) { \
300     free(X); \
301     X=NULL; \
302 }
303 #endif
304 
305 #ifndef FALSE
306 #define FALSE 0
307 #endif
308 
309 #ifndef TRUE
310 #define TRUE !FALSE
311 #endif
312 
313 #ifndef LDAP_FILT_MAXSIZ
314 #define LDAP_FILT_MAXSIZ 1024
315 #endif /* LDAP_FILT_MAXSIZ */
316 
317 #define IGNORE_UNKNOWN_USER	0x01
318 #define IGNORE_AUTHINFO_UNAVAIL	0x02
319 
320 #define STATUS_MAP_IGNORE_POLICY(_rc, _ignore_flags) do { \
321 	if ((_rc) == PAM_USER_UNKNOWN && ((_ignore_flags) & IGNORE_UNKNOWN_USER)) \
322 		rc = PAM_IGNORE; \
323 	else if ((_rc) == PAM_AUTHINFO_UNAVAIL && ((_ignore_flags) & IGNORE_AUTHINFO_UNAVAIL)) \
324 		rc = PAM_IGNORE; \
325 	} while (0)
326 
327 /* PAM authentication routine */
328 #define PAM_SM_AUTH
329 PAM_EXTERN int pam_sm_authenticate (pam_handle_t *, int, int, const char **);
330 PAM_EXTERN int pam_sm_setcred (pam_handle_t *, int, int, const char **);
331 
332 /* PAM session management */
333 #define PAM_SM_SESSION
334 PAM_EXTERN int pam_sm_open_session (pam_handle_t *, int, int, const char **);
335 PAM_EXTERN int pam_sm_close_session (pam_handle_t *, int, int, const char **);
336 
337 /* PAM password changing routine */
338 #define PAM_SM_PASSWORD
339 PAM_EXTERN int pam_sm_chauthtok (pam_handle_t *, int, int, const char **);
340 
341 /* PAM authorization routine */
342 #define PAM_SM_ACCOUNT
343 PAM_EXTERN int pam_sm_acct_mgmt (pam_handle_t *, int, int, const char **);
344 
345