1 /*
2  * Copyright (c) 2008 Alexander Schrijver <aschrijver@openbsd.org>
3  * Copyright (c) 2006, 2007 Marc Balmer <mbalmer@openbsd.org>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include <stdio.h>
19 #include "ber.h"
20 
21 #define LDAP_URL "ldap://"
22 #define LDAP_PORT 389
23 #define LDAP_PAGED_OID  "1.2.840.113556.1.4.319"
24 
25 struct aldap {
26 #define ALDAP_ERR_SUCCESS		0
27 #define ALDAP_ERR_PARSER_ERROR		1
28 #define ALDAP_ERR_INVALID_FILTER	2
29 #define ALDAP_ERR_OPERATION_FAILED	3
30 	uint8_t		err;
31 	int		msgid;
32 	struct ber	ber;
33 };
34 
35 struct aldap_page_control {
36 	int size;
37 	char *cookie;
38 	unsigned int cookie_len;
39 };
40 
41 struct aldap_message {
42 	int msgid;
43 	int message_type;
44 
45 	struct ber_element	*msg;
46 
47 	struct ber_element	*header;
48 	struct ber_element	*protocol_op;
49 
50 	struct ber_element	*dn;
51 
52 	union {
53 		struct {
54 			long long		 rescode;
55 			struct ber_element	*diagmsg;
56 		}			 res;
57 		struct {
58 			struct ber_element	*iter;
59 			struct ber_element	*attrs;
60 		}			 search;
61 	} body;
62 	struct ber_element	*references;
63 	struct aldap_page_control *page;
64 };
65 
66 enum aldap_protocol {
67 	LDAP,
68 	LDAPS
69 };
70 
71 struct aldap_url {
72 	int		 protocol;
73 	char		*host;
74 	in_port_t	 port;
75 	char		*dn;
76 #define MAXATTR 1024
77 	char		*attributes[MAXATTR];
78 	int		 scope;
79 	char		*filter;
80 	char		*buffer;
81 };
82 
83 enum protocol_op {
84 	LDAP_REQ_BIND		= 0,
85 	LDAP_RES_BIND		= 1,
86 	LDAP_REQ_UNBIND_30	= 2,
87 	LDAP_REQ_SEARCH		= 3,
88 	LDAP_RES_SEARCH_ENTRY	= 4,
89 	LDAP_RES_SEARCH_RESULT	= 5,
90 	LDAP_REQ_MODIFY		= 6,
91 	LDAP_RES_MODIFY		= 7,
92 	LDAP_REQ_ADD		= 8,
93 	LDAP_RES_ADD		= 9,
94 	LDAP_REQ_DELETE_30	= 10,
95 	LDAP_RES_DELETE		= 11,
96 	LDAP_REQ_MODRDN		= 12,
97 	LDAP_RES_MODRDN		= 13,
98 	LDAP_REQ_COMPARE	= 14,
99 	LDAP_RES_COMPARE	= 15,
100 	LDAP_REQ_ABANDON_30	= 16,
101 
102 	LDAP_RES_SEARCH_REFERENCE = 19,
103 };
104 
105 enum deref_aliases {
106 	LDAP_DEREF_NEVER	= 0,
107 	LDAP_DEREF_SEARCHING	= 1,
108 	LDAP_DEREF_FINDING	= 2,
109 	LDAP_DEREF_ALWAYS	= 3,
110 };
111 
112 enum authentication_choice {
113 	LDAP_AUTH_SIMPLE	= 0,
114 };
115 
116 enum scope {
117 	LDAP_SCOPE_BASE		= 0,
118 	LDAP_SCOPE_ONELEVEL	= 1,
119 	LDAP_SCOPE_SUBTREE	= 2,
120 };
121 
122 enum result_code {
123 	LDAP_SUCCESS				= 0,
124 	LDAP_OPERATIONS_ERROR			= 1,
125 	LDAP_PROTOCOL_ERROR			= 2,
126 	LDAP_TIMELIMIT_EXCEEDED			= 3,
127 	LDAP_SIZELIMIT_EXCEEDED			= 4,
128 	LDAP_COMPARE_FALSE			= 5,
129 	LDAP_COMPARE_TRUE			= 6,
130 	LDAP_STRONG_AUTH_NOT_SUPPORTED		= 7,
131 	LDAP_STRONG_AUTH_REQUIRED		= 8,
132 
133 	LDAP_REFERRAL				= 10,
134 	LDAP_ADMINLIMIT_EXCEEDED		= 11,
135 	LDAP_UNAVAILABLE_CRITICAL_EXTENSION	= 12,
136 	LDAP_CONFIDENTIALITY_REQUIRED		= 13,
137 	LDAP_SASL_BIND_IN_PROGRESS		= 14,
138 	LDAP_NO_SUCH_ATTRIBUTE			= 16,
139 	LDAP_UNDEFINED_TYPE			= 17,
140 	LDAP_INAPPROPRIATE_MATCHING		= 18,
141 	LDAP_CONSTRAINT_VIOLATION		= 19,
142 	LDAP_TYPE_OR_VALUE_EXISTS		= 20,
143 	LDAP_INVALID_SYNTAX			= 21,
144 
145 	LDAP_NO_SUCH_OBJECT			= 32,
146 	LDAP_ALIAS_PROBLEM			= 33,
147 	LDAP_INVALID_DN_SYNTAX			= 34,
148 
149 	LDAP_ALIAS_DEREF_PROBLEM		= 36,
150 
151 	LDAP_INAPPROPRIATE_AUTH			= 48,
152 	LDAP_INVALID_CREDENTIALS		= 49,
153 	LDAP_INSUFFICIENT_ACCESS		= 50,
154 	LDAP_BUSY				= 51,
155 	LDAP_UNAVAILABLE			= 52,
156 	LDAP_UNWILLING_TO_PERFORM		= 53,
157 	LDAP_LOOP_DETECT			= 54,
158 
159 	LDAP_NAMING_VIOLATION			= 64,
160 	LDAP_OBJECT_CLASS_VIOLATION		= 65,
161 	LDAP_NOT_ALLOWED_ON_NONLEAF		= 66,
162 	LDAP_NOT_ALLOWED_ON_RDN			= 67,
163 	LDAP_ALREADY_EXISTS			= 68,
164 	LDAP_NO_OBJECT_CLASS_MODS		= 69,
165 
166 	LDAP_AFFECTS_MULTIPLE_DSAS		= 71,
167 
168 	LDAP_OTHER				= 80,
169 };
170 
171 enum ldap_filter {
172 	LDAP_FILT_AND		= 0,
173 	LDAP_FILT_OR		= 1,
174 	LDAP_FILT_NOT		= 2,
175 	LDAP_FILT_EQ		= 3,
176 	LDAP_FILT_SUBS		= 4,
177 	LDAP_FILT_GE		= 5,
178 	LDAP_FILT_LE		= 6,
179 	LDAP_FILT_PRES		= 7,
180 	LDAP_FILT_APPR		= 8,
181 };
182 
183 enum ldap_subfilter {
184 	LDAP_FILT_SUBS_INIT	= 0,
185 	LDAP_FILT_SUBS_ANY	= 1,
186 	LDAP_FILT_SUBS_FIN	= 2,
187 };
188 
189 struct aldap		*aldap_init(int fd);
190 int			 aldap_close(struct aldap *);
191 struct aldap_message	*aldap_parse(struct aldap *);
192 void			 aldap_freemsg(struct aldap_message *);
193 
194 int	 aldap_bind(struct aldap *, char *, char *);
195 int	 aldap_unbind(struct aldap *);
196 int	 aldap_search(struct aldap *, char *, enum scope, char *, char **, int, int, int, struct aldap_page_control *);
197 int	 aldap_get_errno(struct aldap *, const char **);
198 
199 int	 aldap_get_resultcode(struct aldap_message *);
200 char	*aldap_get_dn(struct aldap_message *);
201 char	*aldap_get_diagmsg(struct aldap_message *);
202 char	**aldap_get_references(struct aldap_message *);
203 void	 aldap_free_references(char **values);
204 int	 aldap_parse_url(char *, struct aldap_url *);
205 void	 aldap_free_url(struct aldap_url *);
206 #if 0
207 int	 aldap_search_url(struct aldap *, char *, int, int, int);
208 #endif
209 
210 int	 aldap_count_attrs(struct aldap_message *);
211 int	 aldap_match_attr(struct aldap_message *, char *, char ***);
212 int	 aldap_first_attr(struct aldap_message *, char **, char ***);
213 int	 aldap_next_attr(struct aldap_message *, char **, char ***);
214 int	 aldap_free_attr(char **);
215 
216 struct aldap_page_control *aldap_parse_page_control(struct ber_element *, size_t len);
217 void	 aldap_freepage(struct aldap_page_control *);
218