1 /* -*- show-trailing-whitespace: t; indent-tabs: t -*-
2  *
3  * Copyright (c) 2003,2004,2005,2006 David Lichteblau
4  * Copyright (c) 2006 Perry Nguyen
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #include <dirent.h>
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <glib.h>
24 /* fixme: */
25 #define LDAP_DEPRECATED 1
26 #include <ldap.h>
27 #include <ldap_schema.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <sys/ioctl.h>
33 #include <sys/stat.h>
34 #if !defined(__DragonFly__) && !defined(__FreeBSD__)
35 #include <sys/termios.h>
36 #else
37 #include <termios.h>
38 #endif
39 #include <sys/time.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <time.h>
43 #include <unistd.h>
44 #include <ctype.h>
45 
46 #define MANUAL_SYNTAX_URL "http://www.lichteblau.com/ldapvi/manual#syntax"
47 #define MANUAL_LDIF_URL "http://www.lichteblau.com/ldapvi/manual#syntax-ldif"
48 #define RFC_2849_URL "http://www.rfc-editor.org/rfc/rfc2849.txt"
49 
50 typedef struct tschema {
51 	GHashTable *classes;
52 	GHashTable *types;
53 } tschema;
54 
55 typedef struct tentroid {
56 	tschema *schema;
57 	GPtrArray *classes;
58 	GPtrArray *must;
59 	GPtrArray *may;
60 	LDAPObjectClass *structural;
61 	GString *comment;
62 	GString *error;
63 } tentroid;
64 
65 
66 
67 /*
68  * error.c
69  */
70 #define syserr() do_syserr(__FILE__, __LINE__)
71 
72 void do_syserr(char *file, int line);
73 void yourfault(char *str);
74 void ldaperr(LDAP *ld, char *str);
75 
76 /*
77  * arguments.c
78  */
79 enum ldapvi_mode {
80 	ldapvi_mode_edit, ldapvi_mode_in, ldapvi_mode_out,
81 	ldapvi_mode_delete, ldapvi_mode_rename, ldapvi_mode_modrdn
82 };
83 
84 enum bind_dialog {
85 	BD_NEVER = LDAP_SASL_QUIET,
86 	BD_AUTO = LDAP_SASL_AUTOMATIC,
87 	BD_ALWAYS = LDAP_SASL_INTERACTIVE
88 };
89 
90 /* FIXME (?): For now, we recklessly leak all strings stored in
91  * bind_options when reauthentication is performed and new values are
92  * stored. */
93 typedef struct bind_options {
94         ber_tag_t authmethod;   /* LDAP_AUTH_SASL or LDAP_AUTH_NONE */
95         enum bind_dialog dialog;
96         char *user;             /* DN or user search filter */
97         char *password;         /* Simple or SASL passwd */
98         char *sasl_authcid;
99         char *sasl_authzid;
100         char *sasl_mech;
101         char *sasl_realm;
102         char *sasl_secprops;
103 } bind_options;
104 
105 typedef struct cmdline {
106 	char *server;
107 	GPtrArray *basedns;
108 	int scope;
109 	char *filter;
110 	char **attrs;
111 	bind_options bind_options;
112 	int quiet;
113 	int referrals;
114 	GPtrArray *classes;
115 	int ldapmodify_add;
116 	int managedsait;
117 	char *sortkeys;
118 	int starttls;
119 	int tls;
120 	int deref;
121 	int verbose;
122 	int noquestions;
123 	int noninteractive;
124 	int discover;
125 	int config;
126 	int ldif;
127 	int ldapvi;
128 	int mode;
129 	char **delete_dns;
130 	char *rename_old;
131 	char *rename_new;
132 	int rename_dor;
133 	char *in_file;
134 	int schema_comments;
135 	int continuous;
136 	int profileonlyp;
137 } cmdline;
138 
139 void init_cmdline(cmdline *cmdline);
140 void parse_arguments(
141 	int argc, const char **argv, cmdline *result, GPtrArray *ctrls);
142 void usage(int fd, int rc);
143 
144 /*
145  * data.c
146  */
147 typedef struct named_array {
148 	char *name;
149 	GPtrArray *array;
150 } named_array;
151 
152 typedef struct tentry {
153 	struct named_array e;
154 } tentry;
155 #define entry_dn(entry) ((entry)->e.name)
156 #define entry_attributes(entry) ((entry)->e.array)
157 
158 typedef struct tattribute {
159 	struct named_array a;
160 } tattribute;
161 #define attribute_ad(attribute) ((attribute)->a.name)
162 #define attribute_values(attribute) ((attribute)->a.array)
163 
164 tentry *entry_new(char *dn);
165 void entry_free(tentry *e);
166 int entry_cmp(tentry *e, tentry *f);
167 
168 tattribute *attribute_new(char *ad);
169 void attribute_free(tattribute *a);
170 int attribute_cmp(tattribute *a, tattribute *b);
171 
172 int named_array_ptr_cmp(const void *aa, const void *bb);
173 
174 LDAPMod *attribute2mods(tattribute *attribute);
175 LDAPMod **entry2mods(tentry *entry);
176 tattribute *entry_find_attribute(tentry *entry, char *ad, int createp);
177 void attribute_append_value(tattribute *attribute, char *data, int n);
178 int attribute_find_value(tattribute *attribute, char *data, int n);
179 int attribute_remove_value(tattribute *a, char *data, int n);
180 
181 struct berval *string2berval(GArray *s);
182 struct berval *gstring2berval(GString *s);
183 char *array2string(GArray *av);
184 void xfree_berval(struct berval *bv);
185 
186 /*
187  * parse.c
188  */
189 typedef int (*parser_entry)(FILE *, long, char **, tentry **, long *);
190 typedef int (*parser_peek)(FILE *, long, char **, long *);
191 typedef int (*parser_skip)(FILE *, long, char **);
192 typedef int (*parser_rename)(FILE *, long, char **, char **, int *);
193 typedef int (*parser_delete)(FILE *, long, char **);
194 typedef int (*parser_modify)(FILE *, long, char **, LDAPMod ***);
195 typedef void (*print_entry)(FILE *, tentry *, char *, tentroid *);
196 
197 typedef struct tparser {
198 	parser_entry entry;
199 
200 	parser_peek peek;
201 	parser_skip skip;
202 
203 	parser_rename rename;
204 	parser_delete delete;
205 	parser_modify modify;
206 
207 	print_entry print; /* ja, das muss so sein */
208 } tparser;
209 
210 extern tparser ldif_parser;
211 extern tparser ldapvi_parser;
212 
213 int peek_entry(FILE *s, long offset, char **key, long *pos);
214 int read_entry(FILE *s, long offset, char **key, tentry **entry, long *pos);
215 int read_rename(FILE *s, long offset, char **dn1, char **dn2, int *);
216 int read_modify(FILE *s, long offset, char **dn, LDAPMod ***mods);
217 int read_delete(FILE *s, long offset, char **dn);
218 int skip_entry(FILE *s, long offset, char **key);
219 int read_profile(FILE *s, tentry **entry);
220 
221 /*
222  * diff.c
223  */
224 typedef int (*handler_change)(int, char *, char *, LDAPMod **, void *);
225 typedef int (*handler_rename)(int, char *, tentry *, void *);
226 typedef int (*handler_add)(int, char *, LDAPMod **, void *);
227 typedef int (*handler_delete)(int, char *, void *);
228 typedef int (*handler_rename0)(int, char *, char *, int, void *);
229 
230 typedef struct thandler {
231 	handler_change change;
232 	handler_rename rename;
233 	handler_add add;
234 	handler_delete delete;
235 	handler_rename0 rename0;
236 } thandler;
237 
238 int compare_streams(
239 	tparser *parser,
240 	thandler *handler,
241 	void *userdata,
242 	GArray *offsets,
243 	FILE *clean,
244 	FILE *data,
245 	long *error_position,
246 	long *syntax_error_position);
247 
248 enum frob_rdn_mode {
249 	FROB_RDN_CHECK, FROB_RDN_REMOVE, FROB_RDN_ADD, FROB_RDN_CHECK_NONE
250 };
251 int frob_rdn(tentry *entry, char *dn, int mode);
252 int process_immediate(tparser *, thandler *, void *, FILE *, long, char *);
253 
254 
255 /*
256  * misc.c
257  */
258 enum dialog_mode {
259 	DIALOG_DEFAULT, DIALOG_PASSWORD, DIALOG_CHALLENGE
260 };
261 typedef struct dialog {
262 	enum dialog_mode mode;
263 	char *prompt;
264 	char *value;
265 } tdialog;
266 
267 int carray_cmp(GArray *a, GArray *b);
268 int carray_ptr_cmp(const void *aa, const void *bb);
269 void cp(char *src, char *dst, off_t skip, int append);
270 void fcopy(FILE *src, FILE *dst);
271 char choose(char *prompt, char *charbag, char *help);
272 void edit_pos(char *pathname, long pos);
273 void edit(char *pathname, long line);
274 void view(char *pathname);
275 int pipeview(int *fd);
276 void pipeview_wait(int pid);
277 char *home_filename(char *name);
278 void read_ldapvi_history(void);
279 void write_ldapvi_history(void);
280 char *ldapvi_getline(char *prompt, char *value);
281 char *get_password();
282 char *append(char *a, char *b);
283 void *xalloc(size_t size);
284 char *xdup(char *str);
285 int adjoin_str(GPtrArray *, char *);
286 int adjoin_ptr(GPtrArray *, void *);
287 void init_dialog(tdialog *, enum dialog_mode, char *, char *);
288 void dialog(char *header, tdialog *, int, int);
289 
290 /*
291  * schema.c
292  */
293 char *objectclass_name(LDAPObjectClass *);
294 char *attributetype_name(LDAPAttributeType *);
295 
296 tschema *schema_new(LDAP *ld);
297 void schema_free(tschema *schema);
298 LDAPObjectClass *schema_get_objectclass(tschema *, char *);
299 LDAPAttributeType *schema_get_attributetype(tschema *, char *);
300 
301 tentroid *entroid_new(tschema *);
302 void entroid_reset(tentroid *);
303 void entroid_free(tentroid *);
304 LDAPObjectClass *entroid_get_objectclass(tentroid *, char *);
305 LDAPAttributeType *entroid_get_attributetype(tentroid *, char *);
306 LDAPObjectClass *entroid_request_class(tentroid *, char *);
307 int entroid_remove_ad(tentroid *, char *);
308 int compute_entroid(tentroid *);
309 
310 /*
311  * print.c
312  */
313 typedef enum t_print_binary_mode {
314 	PRINT_ASCII, PRINT_UTF8, PRINT_JUNK
315 } t_print_binary_mode;
316 extern t_print_binary_mode print_binary_mode;
317 
318 void print_ldapvi_entry(FILE *s, tentry *entry, char *key, tentroid *);
319 void print_ldapvi_modify(FILE *s, char *dn, LDAPMod **mods);
320 void print_ldapvi_rename(FILE *s, char *olddn, char *newdn, int deleteoldrdn);
321 void print_ldapvi_add(FILE *s, char *dn, LDAPMod **mods);
322 void print_ldapvi_delete(FILE *s, char *dn);
323 void print_ldapvi_modrdn(FILE *s, char *olddn, char *newrdn, int deleteoldrdn);
324 void print_ldapvi_message(FILE *, LDAP *, LDAPMessage *, int key, tentroid *);
325 void print_ldif_entry(FILE *s, tentry *entry, char *key, tentroid *);
326 void print_ldif_modify(FILE *s, char *dn, LDAPMod **mods);
327 void print_ldif_rename(FILE *s, char *olddn, char *newdn, int deleteoldrdn);
328 void print_ldif_add(FILE *s, char *dn, LDAPMod **mods);
329 void print_ldif_delete(FILE *s, char *dn);
330 void print_ldif_modrdn(FILE *s, char *olddn, char *newrdn, int deleteoldrdn);
331 void print_ldif_message(FILE *, LDAP *, LDAPMessage *, int key, tentroid *);
332 
333 /*
334  * search.c
335  */
336 void discover_naming_contexts(LDAP *ld, GPtrArray *basedns);
337 GArray *search(
338 	FILE *s, LDAP *ld, cmdline *cmdline, LDAPControl **ctrls, int notty,
339 	int ldif);
340 LDAPMessage *get_entry(LDAP *ld, char *dn, LDAPMessage **result);
341 
342 /*
343  * port.c
344  */
345 typedef void (*on_exit_function)(int, void *);
346 int g_string_append_sha(GString *string, char *key);
347 int g_string_append_ssha(GString *string, char *key);
348 int g_string_append_md5(GString *string, char *key);
349 int g_string_append_smd5(GString *string, char *key);
350 
351 /*
352  * base64.c
353  */
354 void print_base64(unsigned char const *src, size_t srclength, FILE *s);
355 void g_string_append_base64(
356 	GString *string, unsigned char const *src, size_t srclength);
357 int read_base64(char const *src, unsigned char *target, size_t targsize);
358 
359 /*
360  * sasl.c
361  */
362 typedef struct sasl_defaults {
363 	bind_options *bind_options;
364 	GPtrArray *scratch;
365 	char *pathname;
366 	int fd, out, err;
367 } tsasl_defaults;
368 
369 void init_sasl_redirection(tsasl_defaults *, char *);
370 void enable_sasl_redirection(tsasl_defaults *);
371 void disable_sasl_redirection(tsasl_defaults *);
372 void finish_sasl_redirection(tsasl_defaults *);
373 
374 tsasl_defaults *sasl_defaults_new(bind_options *bind_options);
375 void sasl_defaults_free(tsasl_defaults *sd);
376 int ldapvi_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *p);
377