1/*	$NetBSD: ldapurl.c,v 1.1.1.2 2010/12/12 15:18:13 adam Exp $	*/
2
3/* ldapurl -- a tool for generating LDAP URLs */
4/* OpenLDAP: pkg/ldap/clients/tools/ldapurl.c,v 1.1.2.3 2010/04/13 20:22:23 kurt Exp */
5/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6 *
7 * Copyright 2008-2010 The OpenLDAP Foundation.
8 * Portions Copyright 2008 Pierangelo Masarati, SysNet
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted only as authorized by the OpenLDAP
13 * Public License.
14 *
15 * A copy of this license is available in the file LICENSE in the
16 * top-level directory of the distribution or, alternatively, at
17 * <http://www.OpenLDAP.org/license.html>.
18 */
19/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
20 * All rights reserved.
21 *
22 * Redistribution and use in source and binary forms are permitted
23 * provided that this notice is preserved and that due credit is given
24 * to the University of Michigan at Ann Arbor.  The name of the
25 * University may not be used to endorse or promote products derived
26 * from this software without specific prior written permission.  This
27 * software is provided ``as is'' without express or implied warranty.
28 */
29/* ACKNOWLEDGEMENTS:
30 * This work was originally developed by Pierangelo Masarati
31 * for inclusion in OpenLDAP software.
32 */
33
34#include "portable.h"
35
36#include <ac/stdlib.h>
37#include <stdio.h>
38#include <ac/unistd.h>
39
40#include "ldap.h"
41#include "ldap_pvt.h"
42#include "lutil.h"
43
44static int
45usage(void)
46{
47	fprintf( stderr, _("usage: %s [options]\n\n"), "ldapurl" );
48	fprintf( stderr, _("generates RFC 4516 LDAP URL with extensions\n\n" ) );
49	fprintf( stderr, _("URL options:\n"));
50	fprintf( stderr, _("  -a attrs   comma separated list of attributes\n" ) );
51	fprintf( stderr, _("  -b base    (RFC 4514 LDAP DN)\n" ) );
52	fprintf( stderr, _("  -E ext     (format: \"ext=value\"; multiple occurrences allowed)\n" ) );
53	fprintf( stderr, _("  -f filter  (RFC 4515 LDAP filter)\n" ) );
54	fprintf( stderr, _("  -h host    \n" ) );
55	fprintf( stderr, _("  -p port    (default: 389 for ldap, 636 for ldaps)\n" ) );
56	fprintf( stderr, _("  -s scope   (RFC 4511 searchScope and extensions)\n" ) );
57	fprintf( stderr, _("  -S scheme  (RFC 4516 LDAP URL scheme and extensions)\n" ) );
58	exit( EXIT_FAILURE );
59}
60
61static int
62do_uri_create( LDAPURLDesc *lud )
63{
64	char	*uri;
65
66	if ( lud->lud_scheme == NULL ) {
67		lud->lud_scheme = "ldap";
68	}
69
70	if ( lud->lud_port == -1 ) {
71		if ( strcasecmp( lud->lud_scheme, "ldap" ) == 0 ) {
72			lud->lud_port = LDAP_PORT;
73
74		} else if ( strcasecmp( lud->lud_scheme, "ldaps" ) == 0 ) {
75			lud->lud_port = LDAPS_PORT;
76
77		} else if ( strcasecmp( lud->lud_scheme, "ldapi" ) == 0 ) {
78			lud->lud_port = 0;
79
80		} else {
81			/* forgiving... */
82			lud->lud_port = 0;
83		}
84	}
85
86	if ( lud->lud_scope == -1 ) {
87		lud->lud_scope = LDAP_SCOPE_DEFAULT;
88	}
89
90	uri = ldap_url_desc2str( lud );
91
92	if ( lud->lud_attrs != NULL ) {
93		ldap_charray_free( lud->lud_attrs );
94		lud->lud_attrs = NULL;
95	}
96
97	if ( lud->lud_exts != NULL ) {
98		free( lud->lud_exts );
99		lud->lud_exts = NULL;
100	}
101
102	if ( uri == NULL ) {
103		fprintf( stderr, "unable to generate URI\n" );
104		exit( EXIT_FAILURE );
105	}
106
107	printf( "%s\n", uri );
108	free( uri );
109
110	return 0;
111}
112
113static int
114do_uri_explode( const char *uri )
115{
116	LDAPURLDesc	*lud;
117	int		rc;
118
119	rc = ldap_url_parse( uri, &lud );
120	if ( rc != LDAP_URL_SUCCESS ) {
121		fprintf( stderr, "unable to parse URI \"%s\"\n", uri );
122		return 1;
123	}
124
125	if ( lud->lud_scheme != NULL && lud->lud_scheme[0] != '\0' ) {
126		printf( "scheme: %s\n", lud->lud_scheme );
127	}
128
129	if ( lud->lud_host != NULL && lud->lud_host[0] != '\0' ) {
130		printf( "host: %s\n", lud->lud_host );
131	}
132
133	if ( lud->lud_port != 0 ) {
134		printf( "port: %d\n", lud->lud_port );
135	}
136
137	if ( lud->lud_dn != NULL && lud->lud_dn[0] != '\0' ) {
138		printf( "dn: %s\n", lud->lud_dn );
139	}
140
141	if ( lud->lud_attrs != NULL ) {
142		int	i;
143
144		for ( i = 0; lud->lud_attrs[i] != NULL; i++ ) {
145			printf( "selector: %s\n", lud->lud_attrs[i] );
146		}
147	}
148
149	if ( lud->lud_scope != LDAP_SCOPE_DEFAULT ) {
150		printf( "scope: %s\n", ldap_pvt_scope2str( lud->lud_scope ) );
151	}
152
153	if ( lud->lud_filter != NULL && lud->lud_filter[0] != '\0' ) {
154		printf( "filter: %s\n", lud->lud_filter );
155	}
156
157	if ( lud->lud_exts != NULL ) {
158		int	i;
159
160		for ( i = 0; lud->lud_exts[i] != NULL; i++ ) {
161			printf( "extension: %s\n", lud->lud_exts[i] );
162		}
163	}
164
165	return 0;
166}
167
168int
169main( int argc, char *argv[])
170{
171	LDAPURLDesc	lud = { 0 };
172	char		*uri = NULL;
173	int		gotlud = 0;
174	int		nexts = 0;
175
176	lud.lud_port = -1;
177	lud.lud_scope = -1;
178
179	while ( 1 ) {
180		int opt = getopt( argc, argv, "S:h:p:b:a:s:f:E:H:" );
181
182		if ( opt == EOF ) {
183			break;
184		}
185
186		if ( opt == 'H' ) {
187			if ( gotlud ) {
188				fprintf( stderr, "option -H incompatible with previous options\n" );
189				usage();
190			}
191
192			if ( uri != NULL ) {
193				fprintf( stderr, "URI already provided\n" );
194				usage();
195			}
196
197			uri = optarg;
198			continue;
199		}
200
201		switch ( opt ) {
202		case 'S':
203		case 'h':
204		case 'p':
205		case 'b':
206		case 'a':
207		case 's':
208		case 'f':
209		case 'E':
210			if ( uri != NULL ) {
211				fprintf( stderr, "option -%c incompatible with -H\n", opt );
212				usage();
213			}
214			gotlud++;
215		}
216
217		switch ( opt ) {
218		case 'S':
219			if ( lud.lud_scheme != NULL ) {
220				fprintf( stderr, "scheme already provided\n" );
221				usage();
222			}
223			lud.lud_scheme = optarg;
224			break;
225
226		case 'h':
227			if ( lud.lud_host != NULL ) {
228				fprintf( stderr, "host already provided\n" );
229				usage();
230			}
231			lud.lud_host = optarg;
232			break;
233
234		case 'p':
235			if ( lud.lud_port != -1 ) {
236				fprintf( stderr, "port already provided\n" );
237				usage();
238			}
239
240			if ( lutil_atoi( &lud.lud_port, optarg ) ) {
241				fprintf( stderr, "unable to parse port \"%s\"\n", optarg );
242				usage();
243			}
244			break;
245
246		case 'b':
247			if ( lud.lud_dn != NULL ) {
248				fprintf( stderr, "base already provided\n" );
249				usage();
250			}
251			lud.lud_dn = optarg;
252			break;
253
254		case 'a':
255			if ( lud.lud_attrs != NULL ) {
256				fprintf( stderr, "attrs already provided\n" );
257				usage();
258			}
259			lud.lud_attrs = ldap_str2charray( optarg, "," );
260			if ( lud.lud_attrs == NULL ) {
261				fprintf( stderr, "unable to parse attrs list \"%s\"\n", optarg );
262				usage();
263			}
264			break;
265
266		case 's':
267			if ( lud.lud_scope != -1 ) {
268				fprintf( stderr, "scope already provided\n" );
269				usage();
270			}
271
272			lud.lud_scope = ldap_pvt_str2scope( optarg );
273			if ( lud.lud_scope == -1 ) {
274				fprintf( stderr, "unable to parse scope \"%s\"\n", optarg );
275				usage();
276			}
277			break;
278
279		case 'f':
280			if ( lud.lud_filter != NULL ) {
281				fprintf( stderr, "filter already provided\n" );
282				usage();
283			}
284			lud.lud_filter = optarg;
285			break;
286
287		case 'E':
288			lud.lud_exts = (char **)realloc( lud.lud_exts,
289				sizeof( char * ) * ( nexts + 2 ) );
290			lud.lud_exts[ nexts++ ] = optarg;
291			lud.lud_exts[ nexts ] = NULL;
292			break;
293
294		default:
295			assert( opt != 'H' );
296			usage();
297		}
298	}
299
300	if ( uri != NULL ) {
301		return do_uri_explode( uri );
302
303	}
304
305	return do_uri_create( &lud );
306}
307