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