1 /* $NetBSD: ldapexop.c,v 1.1.1.7 2019/08/08 13:31:09 christos Exp $ */ 2 3 /* ldapexop.c -- a tool for performing well-known extended operations */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2005-2019 The OpenLDAP Foundation. 8 * All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted only as authorized by the OpenLDAP 12 * Public License. 13 * 14 * A copy of this license is available in the file LICENSE in the 15 * top-level directory of the distribution or, alternatively, at 16 * <http://www.OpenLDAP.org/license.html>. 17 */ 18 /* ACKNOWLEDGEMENTS: 19 * This work was originally developed by Pierangelo Masarati for inclusion 20 * in OpenLDAP Software based, in part, on other client tools. 21 */ 22 23 #include <sys/cdefs.h> 24 __RCSID("$NetBSD: ldapexop.c,v 1.1.1.7 2019/08/08 13:31:09 christos Exp $"); 25 26 #include "portable.h" 27 28 #include <stdio.h> 29 30 #include <ac/stdlib.h> 31 32 #include <ac/ctype.h> 33 #include <ac/socket.h> 34 #include <ac/string.h> 35 #include <ac/time.h> 36 #include <ac/unistd.h> 37 38 #include <ldap.h> 39 #include "ldif.h" 40 #include "lutil.h" 41 #include "lutil_ldap.h" 42 #include "ldap_defaults.h" 43 44 #include "common.h" 45 46 void 47 usage( void ) 48 { 49 fprintf( stderr, _("Issue LDAP extended operations\n\n")); 50 fprintf( stderr, _("usage: %s [options] <oid|oid:data|oid::b64data>\n"), prog); 51 fprintf( stderr, _(" %s [options] whoami\n"), prog); 52 fprintf( stderr, _(" %s [options] cancel <id>\n"), prog); 53 fprintf( stderr, _(" %s [options] refresh <DN> [<ttl>]\n"), prog); 54 tool_common_usage(); 55 exit( EXIT_FAILURE ); 56 } 57 58 59 const char options[] = "" 60 "d:D:e:h:H:InNO:o:p:QR:U:vVw:WxX:y:Y:Z"; 61 62 int 63 handle_private_option( int i ) 64 { 65 switch ( i ) { 66 default: 67 return 0; 68 } 69 return 1; 70 } 71 72 73 int 74 main( int argc, char *argv[] ) 75 { 76 int rc; 77 78 LDAP *ld = NULL; 79 80 char *matcheddn = NULL, *text = NULL, **refs = NULL; 81 LDAPControl **ctrls = NULL; 82 int id, code; 83 LDAPMessage *res = NULL; 84 85 tool_init( TOOL_EXOP ); 86 prog = lutil_progname( "ldapexop", argc, argv ); 87 88 /* LDAPv3 only */ 89 protocol = LDAP_VERSION3; 90 91 tool_args( argc, argv ); 92 93 if ( argc - optind < 1 ) { 94 usage(); 95 } 96 97 ld = tool_conn_setup( 0, 0 ); 98 99 tool_bind( ld ); 100 101 argv += optind; 102 argc -= optind; 103 104 if ( strcasecmp( argv[ 0 ], "whoami" ) == 0 ) { 105 tool_server_controls( ld, NULL, 0 ); 106 107 rc = ldap_whoami( ld, NULL, NULL, &id ); 108 if ( rc != LDAP_SUCCESS ) { 109 tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL ); 110 rc = EXIT_FAILURE; 111 goto skip; 112 } 113 114 } else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) { 115 int cancelid; 116 117 switch ( argc ) { 118 case 2: 119 if ( lutil_atoi( &cancelid, argv[ 1 ] ) != 0 || cancelid < 0 ) { 120 fprintf( stderr, "invalid cancelid=%s\n\n", argv[ 1 ] ); 121 usage(); 122 } 123 break; 124 125 default: 126 fprintf( stderr, "need cancelid\n\n" ); 127 usage(); 128 } 129 130 rc = ldap_cancel( ld, cancelid, NULL, NULL, &id ); 131 if ( rc != LDAP_SUCCESS ) { 132 tool_perror( "ldap_cancel", rc, NULL, NULL, NULL, NULL ); 133 rc = EXIT_FAILURE; 134 goto skip; 135 } 136 137 } else if ( strcasecmp( argv[ 0 ], "passwd" ) == 0 ) { 138 fprintf( stderr, "use ldappasswd(1) instead.\n\n" ); 139 usage(); 140 /* TODO? */ 141 142 } else if ( strcasecmp( argv[ 0 ], "refresh" ) == 0 ) { 143 int ttl = 3600; 144 struct berval dn; 145 146 switch ( argc ) { 147 case 3: 148 ttl = atoi( argv[ 2 ] ); 149 150 case 2: 151 dn.bv_val = argv[ 1 ]; 152 dn.bv_len = strlen( dn.bv_val ); 153 break; 154 155 default: 156 fprintf( stderr, _("need DN [ttl]\n\n") ); 157 usage(); 158 } 159 160 tool_server_controls( ld, NULL, 0 ); 161 162 rc = ldap_refresh( ld, &dn, ttl, NULL, NULL, &id ); 163 if ( rc != LDAP_SUCCESS ) { 164 tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL ); 165 rc = EXIT_FAILURE; 166 goto skip; 167 } 168 169 } else { 170 char *p; 171 172 if ( argc != 1 ) { 173 usage(); 174 } 175 176 p = strchr( argv[ 0 ], ':' ); 177 if ( p == argv[ 0 ] ) { 178 usage(); 179 } 180 181 if ( p != NULL ) 182 *p++ = '\0'; 183 184 if ( tool_is_oid( argv[ 0 ] ) ) { 185 struct berval reqdata; 186 struct berval type; 187 struct berval value; 188 int freeval; 189 190 if ( p != NULL ) { 191 p[ -1 ] = ':'; 192 ldif_parse_line2( argv[ 0 ], &type, &value, &freeval ); 193 p[ -1 ] = '\0'; 194 195 if ( freeval ) { 196 reqdata = value; 197 } else { 198 ber_dupbv( &reqdata, &value ); 199 } 200 } 201 202 203 tool_server_controls( ld, NULL, 0 ); 204 205 rc = ldap_extended_operation( ld, argv[ 0 ], p ? &reqdata : NULL, NULL, NULL, &id ); 206 if ( rc != LDAP_SUCCESS ) { 207 tool_perror( "ldap_extended_operation", rc, NULL, NULL, NULL, NULL ); 208 rc = EXIT_FAILURE; 209 goto skip; 210 } 211 } else { 212 fprintf( stderr, "unknown exop \"%s\"\n\n", argv[ 0 ] ); 213 usage(); 214 } 215 } 216 217 for ( ; ; ) { 218 struct timeval tv; 219 220 if ( tool_check_abandon( ld, id ) ) { 221 tool_exit( ld, LDAP_CANCELLED ); 222 } 223 224 tv.tv_sec = 0; 225 tv.tv_usec = 100000; 226 227 rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res ); 228 if ( rc < 0 ) { 229 tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL ); 230 rc = EXIT_FAILURE; 231 goto skip; 232 } 233 234 if ( rc != 0 ) { 235 break; 236 } 237 } 238 239 rc = ldap_parse_result( ld, res, 240 &code, &matcheddn, &text, &refs, &ctrls, 0 ); 241 if ( rc == LDAP_SUCCESS ) { 242 rc = code; 243 } 244 245 if ( rc != LDAP_SUCCESS ) { 246 tool_perror( "ldap_parse_result", rc, NULL, matcheddn, text, refs ); 247 rc = EXIT_FAILURE; 248 goto skip; 249 } 250 251 if ( strcasecmp( argv[ 0 ], "whoami" ) == 0 ) { 252 char *retoid = NULL; 253 struct berval *retdata = NULL; 254 255 rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 0 ); 256 257 if ( rc != LDAP_SUCCESS ) { 258 tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL ); 259 rc = EXIT_FAILURE; 260 goto skip; 261 } 262 263 if ( retdata != NULL ) { 264 if ( retdata->bv_len == 0 ) { 265 printf(_("anonymous\n") ); 266 } else { 267 printf("%s\n", retdata->bv_val ); 268 } 269 } 270 271 ber_memfree( retoid ); 272 ber_bvfree( retdata ); 273 274 } else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) { 275 /* no extended response; returns specific errors */ 276 assert( 0 ); 277 278 } else if ( strcasecmp( argv[ 0 ], "passwd" ) == 0 ) { 279 /* TODO */ 280 281 } else if ( strcasecmp( argv[ 0 ], "refresh" ) == 0 ) { 282 int newttl; 283 284 rc = ldap_parse_refresh( ld, res, &newttl ); 285 286 if ( rc != LDAP_SUCCESS ) { 287 tool_perror( "ldap_parse_refresh", rc, NULL, NULL, NULL, NULL ); 288 rc = EXIT_FAILURE; 289 goto skip; 290 } 291 292 printf( "newttl=%d\n", newttl ); 293 294 } else if ( tool_is_oid( argv[ 0 ] ) ) { 295 char *retoid = NULL; 296 struct berval *retdata = NULL; 297 298 if( ldif < 2 ) { 299 printf(_("# extended operation response\n")); 300 } 301 302 rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 0 ); 303 if ( rc != LDAP_SUCCESS ) { 304 tool_perror( "ldap_parse_extended_result", rc, NULL, NULL, NULL, NULL ); 305 rc = EXIT_FAILURE; 306 goto skip; 307 } 308 309 if ( ldif < 2 && retoid != NULL ) { 310 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_VALUE, 311 "oid", retoid, strlen(retoid) ); 312 } 313 314 ber_memfree( retoid ); 315 316 if( retdata != NULL ) { 317 if ( ldif < 2 ) { 318 tool_write_ldif( ldif ? LDIF_PUT_COMMENT : LDIF_PUT_BINARY, 319 "data", retdata->bv_val, retdata->bv_len ); 320 } 321 322 ber_bvfree( retdata ); 323 } 324 } 325 326 if( verbose || code != LDAP_SUCCESS || 327 ( matcheddn && *matcheddn ) || ( text && *text ) || refs ) { 328 printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code ); 329 330 if( text && *text ) { 331 printf( _("Additional info: %s\n"), text ); 332 } 333 334 if( matcheddn && *matcheddn ) { 335 printf( _("Matched DN: %s\n"), matcheddn ); 336 } 337 338 if( refs ) { 339 int i; 340 for( i=0; refs[i]; i++ ) { 341 printf(_("Referral: %s\n"), refs[i] ); 342 } 343 } 344 } 345 346 if (ctrls) { 347 tool_print_ctrls( ld, ctrls ); 348 ldap_controls_free( ctrls ); 349 } 350 351 ber_memfree( text ); 352 ber_memfree( matcheddn ); 353 ber_memvfree( (void **) refs ); 354 355 skip: 356 /* disconnect from server */ 357 if ( res ) 358 ldap_msgfree( res ); 359 tool_exit( ld, code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE ); 360 } 361