1 /* nssov.h - NSS overlay header file */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4  *
5  * Copyright 2008-2021 The OpenLDAP Foundation.
6  * Portions Copyright 2008 Howard Chu.
7  * Portions Copyright 2013 Ted C. Cheng, Symas Corp.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 #ifndef NSSOV_H
20 #define NSSOV_H
21 
22 #ifndef NSLCD_PATH
23 #define	NSLCD_PATH	"/var/run/nslcd"
24 #endif
25 
26 #ifndef NSLCD_SOCKET
27 #define NSLCD_SOCKET	NSLCD_PATH "/socket"
28 #endif
29 
30 #include <stdio.h>
31 #include <errno.h>
32 
33 #include "nslcd.h"
34 #include "nslcd-prot.h"
35 #include "tio.h"
36 #include "attrs.h"
37 
38 #undef PACKAGE_BUGREPORT
39 #undef PACKAGE_NAME
40 #undef PACKAGE_STRING
41 #undef PACKAGE_TARNAME
42 #undef PACKAGE_VERSION
43 
44 #include "portable.h"
45 #include "slap.h"
46 #include <ac/string.h>
47 
48 /* selectors for different maps */
49 enum nssov_map_selector
50 {
51   NM_alias,
52   NM_ether,
53   NM_group,
54   NM_host,
55   NM_netgroup,
56   NM_network,
57   NM_passwd,
58   NM_protocol,
59   NM_rpc,
60   NM_service,
61   NM_shadow,
62   NM_NONE
63 };
64 
65 typedef struct nssov_mapinfo {
66 	struct berval mi_base;
67 	int mi_scope;
68 	struct berval mi_filter0;
69 	struct berval mi_filter;
70 	struct berval *mi_attrkeys;
71 	AttributeName *mi_attrs;
72 } nssov_mapinfo;
73 
74 typedef struct nssov_info
75 {
76 	/* search timelimit */
77 	int ni_timelimit;
78 	struct nssov_mapinfo ni_maps[NM_NONE];
79 	int ni_socket;
80 	Connection *ni_conn;
81 	BackendDB *ni_db;
82 
83 	/* PAM authz support... */
84 	slap_mask_t ni_pam_opts;
85 	struct berval ni_pam_group_dn;
86 	AttributeDescription *ni_pam_group_ad;
87 	int ni_pam_min_uid;
88 	int ni_pam_max_uid;
89 	AttributeDescription *ni_pam_template_ad;
90 	struct berval ni_pam_template;
91 	struct berval ni_pam_defhost;
92 	struct berval *ni_pam_sessions;
93 	struct berval ni_pam_password_prohibit_message;
94 	struct berval ni_pam_pwdmgr_dn;
95 	struct berval ni_pam_pwdmgr_pwd;
96 } nssov_info;
97 
98 #define NI_PAM_USERHOST		1	/* old style host checking */
99 #define NI_PAM_USERSVC		2	/* old style service checking */
100 #define NI_PAM_USERGRP		4	/* old style group checking */
101 #define NI_PAM_HOSTSVC		8	/* new style authz checking */
102 #define NI_PAM_SASL2DN		0x10	/* use sasl2dn */
103 #define NI_PAM_UID2DN		0x20	/* use uid2dn */
104 
105 #define	NI_PAM_OLD	(NI_PAM_USERHOST|NI_PAM_USERSVC|NI_PAM_USERGRP)
106 #define	NI_PAM_NEW	NI_PAM_HOSTSVC
107 
108 extern AttributeDescription *nssov_pam_host_ad;
109 extern AttributeDescription *nssov_pam_svc_ad;
110 
111 /* Read the default configuration file. */
112 void nssov_cfg_init(nssov_info *ni,const char *fname);
113 
114 /* macros for basic read and write operations, the following
115    ERROR_OUT* marcos define the action taken on errors
116    the stream is not closed because the caller closes the
117    stream */
118 
119 #define ERROR_OUT_WRITEERROR(fp) \
120   Debug(LDAP_DEBUG_ANY,"nssov: error writing to client\n"); \
121   return -1;
122 
123 #define ERROR_OUT_READERROR(fp) \
124   Debug(LDAP_DEBUG_ANY,"nssov: error reading from client\n"); \
125   return -1;
126 
127 #define ERROR_OUT_BUFERROR(fp) \
128   Debug(LDAP_DEBUG_ANY,"nssov: client supplied argument too large\n"); \
129   return -1;
130 
131 #define WRITE_BERVAL(fp, bv)                                                   \
132   DEBUG_PRINT("WRITE_BERVAL: var="__STRING(bv)" bv_val=\"%s\"", (bv)->bv_val); \
133   if ((bv) == NULL)                                                            \
134   {                                                                            \
135     WRITE_INT32(fp, 0);                                                        \
136   }                                                                            \
137   else                                                                         \
138   {                                                                            \
139     WRITE_INT32(fp, (bv)->bv_len);                                             \
140     tmpint32 = ntohl(tmpint32);                                                \
141     if (tmpint32 > 0)                                                          \
142     {                                                                          \
143       WRITE(fp, (bv)->bv_val, tmpint32);                                       \
144     }                                                                          \
145   }                                                                            \
146 
147 #define WRITE_BVARRAY(fp, arr)                                                 \
148   if ((arr) == NULL)                                                           \
149   {                                                                            \
150     DEBUG_PRINT("WRITE_BVARRAY: var="__STRING(arr)" num=%d", 0);               \
151     WRITE_INT32(fp, 0);                                                        \
152   }                                                                            \
153   else                                                                         \
154   {                                                                            \
155     /* first determine length of array */                                      \
156     for (tmp3int32 = 0; (arr)[tmp3int32].bv_val != NULL; tmp3int32++)          \
157       /* nothing */ ;                                                          \
158     /* write number of strings */                                              \
159     DEBUG_PRINT("WRITE_BVARRAY: var="__STRING(arr)" num=%d", (int)tmp3int32);  \
160     WRITE_INT32(fp, tmp3int32);                                                \
161     /* write strings */                                                        \
162     for (tmp2int32 = 0; tmp2int32 < tmp3int32; tmp2int32++)                    \
163     {                                                                          \
164       WRITE_BERVAL(fp, &(arr)[tmp2int32]);                                     \
165     }                                                                          \
166   }                                                                            \
167 
168 /* Find the given attribute's value in the RDN of the DN. */
169 void nssov_find_rdnval(struct berval *dn,AttributeDescription *ad,struct berval *value);
170 
171 /* This tries to get the user password attribute from the entry.
172    It will try to return an encrypted password as it is used in /etc/passwd,
173    /etc/group or /etc/shadow depending upon what is in the directory.
174    This function will return NULL if no passwd is found and will return the
175    literal value in the directory if conversion is not possible. */
176 void get_userpassword(struct berval *attr, struct berval *pw);
177 
178 /* write out an address, parsing the addr value */
179 int write_address(TFILE *fp,struct berval *addr);
180 
181 /* a helper macro to write out addresses and bail out on errors */
182 #define WRITE_ADDRESS(fp,addr) \
183   if (write_address(fp,addr)) \
184     return -1;
185 
186 /* read an address from the stream */
187 int read_address(TFILE *fp,char *addr,int *addrlen,int *af);
188 
189 /* helper macro to read an address from the stream */
190 #define READ_ADDRESS(fp,addr,len,af) \
191   len=(int)sizeof(addr); \
192   if (read_address(fp,addr,&(len),&(af))) \
193     return -1;
194 
195 /* checks to see if the specified string is a valid username */
196 int isvalidusername(struct berval *name);
197 
198 /* transforms the DN into a uid doing an LDAP lookup if needed */
199 int nssov_dn2uid(Operation *op,nssov_info *ni,struct berval *dn,struct berval *uid);
200 
201 /* transforms the uid into a DN by doing an LDAP lookup */
202 int nssov_uid2dn(Operation *op,nssov_info *ni,struct berval *uid,struct berval *dn);
203 int nssov_name2dn_cb(Operation *op, SlapReply *rs);
204 
205 /* Escapes characters in a string for use in a search filter. */
206 int nssov_escape(struct berval *src,struct berval *dst);
207 
208 int nssov_filter_byname(nssov_mapinfo *mi,int key,struct berval *name,struct berval *buf);
209 int nssov_filter_byid(nssov_mapinfo *mi,int key,struct berval *id,struct berval *buf);
210 
211 void nssov_alias_init(nssov_info *ni);
212 void nssov_ether_init(nssov_info *ni);
213 void nssov_group_init(nssov_info *ni);
214 void nssov_host_init(nssov_info *ni);
215 void nssov_netgroup_init(nssov_info *ni);
216 void nssov_network_init(nssov_info *ni);
217 void nssov_passwd_init(nssov_info *ni);
218 void nssov_protocol_init(nssov_info *ni);
219 void nssov_rpc_init(nssov_info *ni);
220 void nssov_service_init(nssov_info *ni);
221 void nssov_shadow_init(nssov_info *ni);
222 
223 int nssov_pam_init(void);
224 
225 /* these are the different functions that handle the database
226    specific actions, see nslcd.h for the action descriptions */
227 int nssov_alias_byname(nssov_info *ni,TFILE *fp,Operation *op);
228 int nssov_alias_all(nssov_info *ni,TFILE *fp,Operation *op);
229 int nssov_ether_byname(nssov_info *ni,TFILE *fp,Operation *op);
230 int nssov_ether_byether(nssov_info *ni,TFILE *fp,Operation *op);
231 int nssov_ether_all(nssov_info *ni,TFILE *fp,Operation *op);
232 int nssov_group_byname(nssov_info *ni,TFILE *fp,Operation *op);
233 int nssov_group_bygid(nssov_info *ni,TFILE *fp,Operation *op);
234 int nssov_group_bymember(nssov_info *ni,TFILE *fp,Operation *op);
235 int nssov_group_all(nssov_info *ni,TFILE *fp,Operation *op);
236 int nssov_host_byname(nssov_info *ni,TFILE *fp,Operation *op);
237 int nssov_host_byaddr(nssov_info *ni,TFILE *fp,Operation *op);
238 int nssov_host_all(nssov_info *ni,TFILE *fp,Operation *op);
239 int nssov_netgroup_byname(nssov_info *ni,TFILE *fp,Operation *op);
240 int nssov_network_byname(nssov_info *ni,TFILE *fp,Operation *op);
241 int nssov_network_byaddr(nssov_info *ni,TFILE *fp,Operation *op);
242 int nssov_network_all(nssov_info *ni,TFILE *fp,Operation *op);
243 int nssov_passwd_byname(nssov_info *ni,TFILE *fp,Operation *op);
244 int nssov_passwd_byuid(nssov_info *ni,TFILE *fp,Operation *op);
245 int nssov_passwd_all(nssov_info *ni,TFILE *fp,Operation *op);
246 int nssov_protocol_byname(nssov_info *ni,TFILE *fp,Operation *op);
247 int nssov_protocol_bynumber(nssov_info *ni,TFILE *fp,Operation *op);
248 int nssov_protocol_all(nssov_info *ni,TFILE *fp,Operation *op);
249 int nssov_rpc_byname(nssov_info *ni,TFILE *fp,Operation *op);
250 int nssov_rpc_bynumber(nssov_info *ni,TFILE *fp,Operation *op);
251 int nssov_rpc_all(nssov_info *ni,TFILE *fp,Operation *op);
252 int nssov_service_byname(nssov_info *ni,TFILE *fp,Operation *op);
253 int nssov_service_bynumber(nssov_info *ni,TFILE *fp,Operation *op);
254 int nssov_service_all(nssov_info *ni,TFILE *fp,Operation *op);
255 int nssov_shadow_byname(nssov_info *ni,TFILE *fp,Operation *op);
256 int nssov_shadow_all(nssov_info *ni,TFILE *fp,Operation *op);
257 int pam_authc(nssov_info *ni,TFILE *fp,Operation *op,uid_t calleruid);
258 int pam_authz(nssov_info *ni,TFILE *fp,Operation *op);
259 int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op);
260 int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op);
261 int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op,uid_t calleruid);
262 
263 /* config initialization */
264 #define NSSOV_INIT(db) \
265  void nssov_##db##_init(nssov_info *ni) \
266  { \
267 	nssov_mapinfo *mi = &ni->ni_maps[NM_##db]; \
268 	int i; \
269 	for (i=0;!BER_BVISNULL(&db##_keys[i]);i++); \
270 	i++; \
271 	mi->mi_attrs = ch_malloc( i*sizeof(AttributeName)); \
272 	for (i=0;!BER_BVISNULL(&db##_keys[i]);i++) { \
273 		mi->mi_attrs[i].an_name = db##_keys[i]; \
274 		mi->mi_attrs[i].an_desc = NULL; \
275 	} \
276 	mi->mi_scope = LDAP_SCOPE_DEFAULT; \
277 	mi->mi_filter0 = db##_filter; \
278 	ber_dupbv( &mi->mi_filter, &mi->mi_filter0 ); \
279 	mi->mi_filter = db##_filter; \
280 	mi->mi_attrkeys = db##_keys; \
281 	BER_BVZERO(&mi->mi_base); \
282  }
283 
284 /* param structure for search callback */
285 #define NSSOV_CBPRIV(db,parms) \
286   typedef struct nssov_##db##_cbp { \
287   	nssov_mapinfo *mi; \
288 	TFILE *fp; \
289 	Operation *op; \
290 	parms \
291   } nssov_##db##_cbp
292 
293 /* callback for writing search results */
294 #define NSSOV_CB(db) \
295   static int nssov_##db##_cb(Operation *op, SlapReply *rs) \
296   { \
297     if ( rs->sr_type == REP_SEARCH ) { \
298     nssov_##db##_cbp *cbp = op->o_callback->sc_private; \
299   	if (write_##db(cbp,rs->sr_entry)) return LDAP_OTHER; \
300   } \
301   return LDAP_SUCCESS; \
302   } \
303 
304 /* macro for generating service handling code */
305 #define NSSOV_HANDLE(db,fn,readfn,logcall,action,mkfilter) \
306   int nssov_##db##_##fn(nssov_info *ni,TFILE *fp,Operation *op) \
307   { \
308     /* define common variables */ \
309     int32_t tmpint32; \
310 	nssov_##db##_cbp cbp; \
311 	slap_callback cb = {0}; \
312 	SlapReply rs = {REP_RESULT}; \
313 	cbp.mi = &ni->ni_maps[NM_##db]; \
314 	cbp.fp = fp; \
315 	cbp.op = op; \
316     /* read request parameters */ \
317     readfn; \
318     /* log call */ \
319     logcall; \
320     /* write the response header */ \
321     WRITE_INT32(fp,NSLCD_VERSION); \
322     WRITE_INT32(fp,action); \
323     /* prepare the search filter */ \
324     if (mkfilter) \
325     { \
326       Debug(LDAP_DEBUG_ANY,"nssov_" __STRING(db) "_" __STRING(fn) "(): filter buffer too small"); \
327       return -1; \
328     } \
329 	cb.sc_private = &cbp; \
330 	op->o_callback = &cb; \
331 	cb.sc_response = nssov_##db##_cb; \
332 	slap_op_time( &op->o_time, &op->o_tincr ); \
333 	op->o_req_dn = cbp.mi->mi_base; \
334 	op->o_req_ndn = cbp.mi->mi_base; \
335 	op->ors_scope = cbp.mi->mi_scope; \
336 	op->ors_filterstr = filter; \
337 	op->ors_filter = str2filter_x( op, filter.bv_val ); \
338 	op->ors_attrs = cbp.mi->mi_attrs; \
339 	op->ors_tlimit = SLAP_NO_LIMIT; \
340 	op->ors_slimit = SLAP_NO_LIMIT; \
341     /* do the internal search */ \
342 	op->o_bd->be_search( op, &rs ); \
343 	filter_free_x( op, op->ors_filter, 1 ); \
344 	WRITE_INT32(fp,NSLCD_RESULT_END); \
345     return 0; \
346   }
347 
348 #endif /* NSSOV_H */
349