From 4cef770d2b1b4fb11bdedd65b6dd67eb5267ccdb Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Sun, 19 Oct 2008 20:35:18 +0000 Subject: [PATCH] add ldapurl command --- clients/tools/Makefile.in | 17 ++- clients/tools/ldapurl.c | 304 ++++++++++++++++++++++++++++++++++++++ doc/devel/args | 1 + doc/man/man1/ldapurl.1 | 141 ++++++++++++++++++ 4 files changed, 459 insertions(+), 4 deletions(-) create mode 100644 clients/tools/ldapurl.c create mode 100644 doc/man/man1/ldapurl.1 diff --git a/clients/tools/Makefile.in b/clients/tools/Makefile.in index 6fd0578fae..e8b70556cb 100644 --- a/clients/tools/Makefile.in +++ b/clients/tools/Makefile.in @@ -15,10 +15,10 @@ SRCS = ldapsearch.c ldapmodify.c ldapdelete.c ldapmodrdn.c \ ldappasswd.c ldapwhoami.c ldapcompare.c \ - ldapexop.c common.c + ldapexop.c ldapurl.c common.c OBJS = ldapsearch.o ldapmodify.o ldapdelete.o ldapmodrdn.o \ ldappasswd.o ldapwhoami.o ldapcompare.o \ - ldapexop.o common.o + ldapexop.o ldapurl.o common.o LDAP_INCDIR= ../../include LDAP_LIBDIR= ../../libraries @@ -29,10 +29,10 @@ XLIBS = $(LDAP_L) XXLIBS = $(SECURITY_LIBS) $(LUTIL_LIBS) XSRCS = ldsversion.c ldmversion.c lddversion.c ldrversion.c \ - ldpversion.c ldwversion.c ldcversion.c ldeversion.c + ldpversion.c ldwversion.c ldcversion.c ldeversion.c lduversion.c PROGRAMS = ldapsearch ldapmodify ldapdelete ldapmodrdn \ - ldappasswd ldapwhoami ldapcompare ldapexop + ldappasswd ldapwhoami ldapcompare ldapexop ldapurl ldapsearch: ldsversion.o @@ -59,6 +59,9 @@ ldapcompare: ldcversion.o ldapexop: ldeversion.o $(LTLINK) -o $@ ldapexop.o common.o ldeversion.o $(LIBS) +ldapurl: lduversion.o + $(LTLINK) -o $@ ldapurl.o lduversion.o $(LIBS) + ldsversion.c: Makefile @-$(RM) $@ $(MKVERSION) $(MKVOPTS) ldapsearch > $@ @@ -107,6 +110,12 @@ ldeversion.c: Makefile ldeversion.o: ldapexop.o common.o $(XLIBS) +lduversion.c: Makefile + @-$(RM) $@ + $(MKVERSION) $(MKVOPTS) ldapurl > $@ + +lduversion.o: ldapurl.o $(XLIBS) + install-local: FORCE -$(MKDIR) $(DESTDIR)$(bindir) @( \ diff --git a/clients/tools/ldapurl.c b/clients/tools/ldapurl.c new file mode 100644 index 0000000000..eb7f964ed6 --- /dev/null +++ b/clients/tools/ldapurl.c @@ -0,0 +1,304 @@ +/* ldapurl -- a tool for generating LDAP URLs */ +/* $OpenLDAP$ */ +/* This work is part of OpenLDAP Software . + * + * Copyright 2008 The OpenLDAP Foundation. + * Portions Copyright 2008 Pierangelo Masarati, SysNet + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted only as authorized by the OpenLDAP + * Public License. + * + * A copy of this license is available in the file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* Portions Copyright (c) 1992-1996 Regents of the University of Michigan. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of Michigan at Ann Arbor. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. This + * software is provided ``as is'' without express or implied warranty. + */ +/* ACKNOWLEDGEMENTS: + * This work was originally developed by Pierangelo Masarati + * for inclusion in OpenLDAP software. + */ + +#include "portable.h" + +#include +#include +#include + +#include "ldap.h" +#include "ldap_pvt.h" +#include "lutil.h" + +static int +usage(void) +{ + fprintf( stderr, _("usage: %s [options]\n\n"), "ldapurl" ); + fprintf( stderr, _("generates RFC 4516 LDAP URL with extensions\n\n" ) ); + fprintf( stderr, _("URL options:\n")); + fprintf( stderr, _(" -a attrs comma separated list of attributes\n" ) ); + fprintf( stderr, _(" -b base (RFC 4514 LDAP DN)\n" ) ); + fprintf( stderr, _(" -E ext (format: \"ext=value\"; multiple occurrences allowed)\n" ) ); + fprintf( stderr, _(" -f filter (RFC 4515 LDAP filter)\n" ) ); + fprintf( stderr, _(" -h host \n" ) ); + fprintf( stderr, _(" -p port (default: 389 for ldap, 636 for ldaps)\n" ) ); + fprintf( stderr, _(" -s scope (RFC 4511 searchScope and extensions)\n" ) ); + fprintf( stderr, _(" -S scheme (RFC 4516 LDAP URL scheme and extensions)\n" ) ); + exit( EXIT_FAILURE ); +} + +static int +do_uri_create( LDAPURLDesc *lud ) +{ + char *uri; + + if ( lud->lud_scheme == NULL ) { + lud->lud_scheme = "ldap"; + } + + if ( lud->lud_port == -1 ) { + if ( strcasecmp( lud->lud_scheme, "ldap" ) == 0 ) { + lud->lud_port = LDAP_PORT; + + } else if ( strcasecmp( lud->lud_scheme, "ldaps" ) == 0 ) { + lud->lud_port = LDAPS_PORT; + + } else if ( strcasecmp( lud->lud_scheme, "ldapi" ) == 0 ) { + lud->lud_port = 0; + + } else { + /* forgiving... */ + lud->lud_port = 0; + } + } + + if ( lud->lud_scope == -1 ) { + lud->lud_scope = LDAP_SCOPE_DEFAULT; + } + + uri = ldap_url_desc2str( lud ); + + if ( lud->lud_attrs != NULL ) { + ldap_charray_free( lud->lud_attrs ); + lud->lud_attrs = NULL; + } + + if ( lud->lud_exts != NULL ) { + free( lud->lud_exts ); + lud->lud_exts = NULL; + } + + if ( uri == NULL ) { + fprintf( stderr, "unable to generate URI\n" ); + exit( EXIT_FAILURE ); + } + + printf( "%s\n", uri ); + free( uri ); + + return 0; +} + +static int +do_uri_explode( const char *uri ) +{ + LDAPURLDesc *lud; + int rc; + + rc = ldap_url_parse( uri, &lud ); + if ( rc != LDAP_URL_SUCCESS ) { + fprintf( stderr, "unable to parse URI \"%s\"\n", uri ); + return 1; + } + + if ( lud->lud_scheme != NULL && lud->lud_scheme[0] != '\0' ) { + printf( "scheme: %s\n", lud->lud_scheme ); + } + + if ( lud->lud_host != NULL && lud->lud_host[0] != '\0' ) { + printf( "host: %s\n", lud->lud_host ); + } + + if ( lud->lud_port != 0 ) { + printf( "port: %d\n", lud->lud_port ); + } + + if ( lud->lud_dn != NULL && lud->lud_dn[0] != '\0' ) { + printf( "dn: %s\n", lud->lud_dn ); + } + + if ( lud->lud_attrs != NULL ) { + int i; + + for ( i = 0; lud->lud_attrs[i] != NULL; i++ ) { + printf( "selector: %s\n", lud->lud_attrs[i] ); + } + } + + if ( lud->lud_scope != LDAP_SCOPE_DEFAULT ) { + printf( "scope: %s\n", ldap_pvt_scope2str( lud->lud_scope ) ); + } + + if ( lud->lud_filter != NULL && lud->lud_filter[0] != '\0' ) { + printf( "filter: %s\n", lud->lud_filter ); + } + + if ( lud->lud_exts != NULL ) { + int i; + + for ( i = 0; lud->lud_exts[i] != NULL; i++ ) { + printf( "extension: %s\n", lud->lud_exts[i] ); + } + } + + return 0; +} + +int +main( int argc, char *argv[]) +{ + LDAPURLDesc lud = { 0 }; + char *uri = NULL; + int gotlud = 0; + int nexts = 0; + + lud.lud_port = -1; + lud.lud_scope = -1; + + while ( 1 ) { + int opt = getopt( argc, argv, "S:h:p:b:a:s:f:E:H:" ); + + if ( opt == EOF ) { + break; + } + + if ( opt == 'H' ) { + if ( gotlud ) { + fprintf( stderr, "option -H incompatible with previous options\n" ); + usage(); + } + + if ( uri != NULL ) { + fprintf( stderr, "URI already provided\n" ); + usage(); + } + + uri = optarg; + continue; + } + + switch ( opt ) { + case 'S': + case 'h': + case 'p': + case 'b': + case 'a': + case 's': + case 'f': + case 'E': + if ( uri != NULL ) { + fprintf( stderr, "option -%c incompatible with -H\n", opt ); + usage(); + } + gotlud++; + } + + switch ( opt ) { + case 'S': + if ( lud.lud_scheme != NULL ) { + fprintf( stderr, "scheme already provided\n" ); + usage(); + } + lud.lud_scheme = optarg; + break; + + case 'h': + if ( lud.lud_host != NULL ) { + fprintf( stderr, "host already provided\n" ); + usage(); + } + lud.lud_host = optarg; + break; + + case 'p': + if ( lud.lud_port != -1 ) { + fprintf( stderr, "port already provided\n" ); + usage(); + } + + if ( lutil_atoi( &lud.lud_port, optarg ) ) { + fprintf( stderr, "unable to parse port \"%s\"\n", optarg ); + usage(); + } + break; + + case 'b': + if ( lud.lud_dn != NULL ) { + fprintf( stderr, "base already provided\n" ); + usage(); + } + lud.lud_dn = optarg; + break; + + case 'a': + if ( lud.lud_attrs != NULL ) { + fprintf( stderr, "attrs already provided\n" ); + usage(); + } + lud.lud_attrs = ldap_str2charray( optarg, "," ); + if ( lud.lud_attrs == NULL ) { + fprintf( stderr, "unable to parse attrs list \"%s\"\n", optarg ); + usage(); + } + break; + + case 's': + if ( lud.lud_scope != -1 ) { + fprintf( stderr, "scope already provided\n" ); + usage(); + } + + lud.lud_scope = ldap_pvt_str2scope( optarg ); + if ( lud.lud_scope == -1 ) { + fprintf( stderr, "unable to parse scope \"%s\"\n", optarg ); + usage(); + } + break; + + case 'f': + if ( lud.lud_filter != NULL ) { + fprintf( stderr, "filter already provided\n" ); + usage(); + } + lud.lud_filter = optarg; + break; + + case 'E': + lud.lud_exts = (char **)realloc( lud.lud_exts, + sizeof( char * ) * ( nexts + 2 ) ); + lud.lud_exts[ nexts++ ] = optarg; + lud.lud_exts[ nexts ] = NULL; + break; + + default: + assert( opt != 'H' ); + usage(); + } + } + + if ( uri != NULL ) { + return do_uri_explode( uri ); + + } + + return do_uri_create( &lud ); +} diff --git a/doc/devel/args b/doc/devel/args index 69316da0f5..60de07df78 100644 --- a/doc/devel/args +++ b/doc/devel/args @@ -5,6 +5,7 @@ ldapmodify *CDE**HI*K M*OPQRS UVWXYZabcde *h**k *nop*r t vwxy ldapmodrdn *CDE**HI*K M*OPQR UVWXYZ cdef*h**k *nop*rs vwxy ldappasswd A*CDE**HI* *O QRS UVWXYZa def*h** * o * s vwxy ldapsearch A*CDE**HI*KLM*OPQRSTUVWXYZab def*h**kl*nop* stuvwxyz +ldapurl * E**H * * S ab f*h** * p* s ldapwhoami * DE**HI* *O QR UVWXYZ def*h** *nop* vwxy diff --git a/doc/man/man1/ldapurl.1 b/doc/man/man1/ldapurl.1 new file mode 100644 index 0000000000..3806133d1d --- /dev/null +++ b/doc/man/man1/ldapurl.1 @@ -0,0 +1,141 @@ +.TH LDAPURL 1 "RELEASEDATE" "OpenLDAP LDVERSION" +.\" $OpenLDAP$ +.\" Copyright 2008 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.SH NAME +ldapurl \- LDAP URL formatting tool +.SH SYNOPSIS +.B ldapurl +[\c +.BR \-a \ attrs\fR] +[\c +.BI \-b \ searchbase\fR] +[\c +.BR \-E \ [!]ext[=extparam]] +[\c +.BI \-f \ filter\fR] +[\c +.BI \-H \ ldapuri\fR] +[\c +.BI \-h \ ldaphost\fR] +[\c +.BI \-p \ ldapport\fR] +[\c +.BI \-s \ base\fR\||\|\fIone\fR\||\|\fIsub\fR\||\|\fIchildren\fR] +[\c +.BI \-S \ scheme\fR] +.SH DESCRIPTION +.I ldapurl +is a command that allows to either compose or decompose LDAP URIs. +.LP +When invoked with the \fI-H\fP option, +.B ldapurl +extracts the components of the \fIldapuri\fP option argument, +unescaping hex-escaped chars as required. +It basically acts as a frontend to the +.BR ldap_url_parse (3) +call. +Otherwise, it builds an LDAP URI based on the components +passed with the appropriate options, performing the inverse operation. +Option \fI-H\fP is incompatible with options +.IR \-a , +.IR \-b , +.IR \-E , +.IR \-f , +.IR \-H , +.IR \-h , +.IR \-p , +.IR \-S , +and +.IR \-s . +.SH OPTIONS +.TP +.TP +.BI \-a \ attrs +Set a comma-separated list of attribute selectors. +.TP +.BI \-b \ searchbase +Set the \fIsearchbase\fP. +.TP +.B \-E \fI[!]ext[=extparam]\fP +Set URL extensions; \'!\' indicates criticality. +.TP +.BI \-f \ filter +Set the URL filter. No particular check on conformity with RFC 4515 +LDAP filters is performed, but the value is hex-escaped as required. +.TP +.BI \-H \ ldapuri +Specify URI to be exploded. +.TP +.BI \-h \ ldaphost +Set the host. +.TP +.BI \-p \ ldapport +Set the TCP port. +.TP +.BI \-S \ scheme +Set the URL scheme. Defaults for other fields, like \fIldapport\fP, +may depend on the value of \fIscheme\fP. +.TP +.BI \-s \ base\fR\||\|\fIone\fR\||\|\fIsub\fR\||\|\fIchildren +Specify the scope of the search to be one of +.IR base , +.IR one , +.IR sub , +or +.I children +to specify a base object, one-level, subtree, or children search. +The default is +.IR sub . +Note: +.I children +scope requires LDAPv3 subordinate feature extension. + +.SH OUTPUT FORMAT +If the \fI-H\fP option is used, the \fIldapuri\fP supplied +is exploded in its components, which are printed to standard output +in an LDIF-like form. +.LP +Otherwise, the URI built using the values passed with the other options +is printed to standard output. +.SH EXAMPLE +The following command: +.LP +.nf + ldapuri -h ldap.example.com -b dc=example,dc=com -s sub -f (cn=Some One) +.fi +.LP +returns +.LP +.nf + ldap://ldap.example.com:389/dc=example,dc=com??sub?(cn=Some%20One) +.fi +.LP +The command: +.LP +.nf + ldapuri -H ldap://ldap.example.com:389/dc=example,dc=com??sub?(cn=Some%20One) +.fi +.LP +returns +.LP +.nf + scheme: ldap + host: ldap.example.com + port: 389 + dn: dc=example,dc=com + scope: sub + filter: (cn=Some One) +.fi +.LP +.SH DIAGNOSTICS +Exit status is zero if no errors occur. +Errors result in a non-zero exit status and +a diagnostic message being written to standard error. +.SH "SEE ALSO" +.BR ldap (3), +.BR ldap_url_parse (3), +.SH AUTHOR +The OpenLDAP Project +.SH ACKNOWLEDGEMENTS +.so ../Project -- 2.39.5