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