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-2021 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 #include <ac/socket.h>
38 
39 #include "ldap.h"
40 #include "ldap_pvt.h"
41 #include "lutil.h"
42 
43 static int
usage(void)44 usage(void)
45 {
46 	fprintf( stderr, _("usage: %s [options]\n\n"), "ldapurl" );
47 	fprintf( stderr, _("generates RFC 4516 LDAP URL with extensions\n\n" ) );
48 	fprintf( stderr, _("URL options:\n"));
49 	fprintf( stderr, _("  -a attrs   comma separated list of attributes\n" ) );
50 	fprintf( stderr, _("  -b base    (RFC 4514 LDAP DN)\n" ) );
51 	fprintf( stderr, _("  -E ext     (format: \"ext=value\"; multiple occurrences allowed)\n" ) );
52 	fprintf( stderr, _("  -f filter  (RFC 4515 LDAP filter)\n" ) );
53 	fprintf( stderr, _("  -h host    \n" ) );
54 	fprintf( stderr, _("  -p port    (default: 389 for ldap, 636 for ldaps)\n" ) );
55 	fprintf( stderr, _("  -s scope   (RFC 4511 searchScope and extensions)\n" ) );
56 	fprintf( stderr, _("  -S scheme  (RFC 4516 LDAP URL scheme and extensions)\n" ) );
57 	exit( EXIT_FAILURE );
58 }
59 
60 static int
do_uri_create(LDAPURLDesc * lud)61 do_uri_create( LDAPURLDesc *lud )
62 {
63 	char	*uri;
64 
65 	if ( lud->lud_scheme == NULL ) {
66 		lud->lud_scheme = "ldap";
67 	}
68 
69 	if ( lud->lud_port == -1 ) {
70 		if ( strcasecmp( lud->lud_scheme, "ldap" ) == 0 ) {
71 			lud->lud_port = LDAP_PORT;
72 
73 		} else if ( strcasecmp( lud->lud_scheme, "ldaps" ) == 0 ) {
74 			lud->lud_port = LDAPS_PORT;
75 
76 		} else if ( strcasecmp( lud->lud_scheme, "ldapi" ) == 0 ) {
77 			lud->lud_port = 0;
78 
79 		} else {
80 			/* forgiving... */
81 			lud->lud_port = 0;
82 		}
83 	}
84 
85 	if ( lud->lud_scope == -1 ) {
86 		lud->lud_scope = LDAP_SCOPE_DEFAULT;
87 	}
88 
89 	uri = ldap_url_desc2str( lud );
90 
91 	if ( lud->lud_attrs != NULL ) {
92 		ldap_charray_free( lud->lud_attrs );
93 		lud->lud_attrs = NULL;
94 	}
95 
96 	if ( lud->lud_exts != NULL ) {
97 		free( lud->lud_exts );
98 		lud->lud_exts = NULL;
99 	}
100 
101 	if ( uri == NULL ) {
102 		fprintf( stderr, "unable to generate URI\n" );
103 		exit( EXIT_FAILURE );
104 	}
105 
106 	printf( "%s\n", uri );
107 	free( uri );
108 
109 	return 0;
110 }
111 
112 static int
do_uri_explode(const char * uri)113 do_uri_explode( const char *uri )
114 {
115 	LDAPURLDesc	*lud;
116 	int		rc;
117 
118 	rc = ldap_url_parse( uri, &lud );
119 	if ( rc != LDAP_URL_SUCCESS ) {
120 		fprintf( stderr, "unable to parse URI \"%s\"\n", uri );
121 		return 1;
122 	}
123 
124 	if ( lud->lud_scheme != NULL && lud->lud_scheme[0] != '\0' ) {
125 		printf( "scheme: %s\n", lud->lud_scheme );
126 	}
127 
128 	if ( lud->lud_host != NULL && lud->lud_host[0] != '\0' ) {
129 		printf( "host: %s\n", lud->lud_host );
130 	}
131 
132 	if ( lud->lud_port != 0 ) {
133 		printf( "port: %d\n", lud->lud_port );
134 	}
135 
136 	if ( lud->lud_dn != NULL && lud->lud_dn[0] != '\0' ) {
137 		printf( "dn: %s\n", lud->lud_dn );
138 	}
139 
140 	if ( lud->lud_attrs != NULL ) {
141 		int	i;
142 
143 		for ( i = 0; lud->lud_attrs[i] != NULL; i++ ) {
144 			printf( "selector: %s\n", lud->lud_attrs[i] );
145 		}
146 	}
147 
148 	if ( lud->lud_scope != LDAP_SCOPE_DEFAULT ) {
149 		printf( "scope: %s\n", ldap_pvt_scope2str( lud->lud_scope ) );
150 	}
151 
152 	if ( lud->lud_filter != NULL && lud->lud_filter[0] != '\0' ) {
153 		printf( "filter: %s\n", lud->lud_filter );
154 	}
155 
156 	if ( lud->lud_exts != NULL ) {
157 		int	i;
158 
159 		for ( i = 0; lud->lud_exts[i] != NULL; i++ ) {
160 			printf( "extension: %s\n", lud->lud_exts[i] );
161 		}
162 	}
163 	ldap_free_urldesc( lud );
164 
165 	return 0;
166 }
167 
168 int
main(int argc,char * argv[])169 main( 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