2010-12-15 09:41:30 +08:00
/* ldapvc.c -- a tool for verifying credentials */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
2013-01-03 02:20:30 +08:00
* Copyright 1998 - 2013 The OpenLDAP Foundation .
2010-12-15 09:41:30 +08:00
* Portions Copyright 2010 Kurt D . Zeilenga .
* 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
* < http : //www.OpenLDAP.org/license.html>.
*/
/* 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 Kurt D . Zeilenga for inclusion
* in OpenLDAP Software based , in part , on other client tools .
*/
# include "portable.h"
# include <stdio.h>
# include <ac/stdlib.h>
# include <ac/ctype.h>
# include <ac/socket.h>
# include <ac/string.h>
# include <ac/time.h>
# include <ac/unistd.h>
# include <ldap.h>
# include "lutil.h"
# include "lutil_ldap.h"
# include "ldap_defaults.h"
# include "common.h"
2011-01-04 06:54:48 +08:00
static int req_authzid = 0 ;
static int req_pp = 0 ;
2011-01-07 02:37:23 +08:00
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
# define LDAP_SASL_NONE (~0U)
static unsigned vc_sasl = LDAP_SASL_NONE ;
static char * vc_sasl_realm = NULL ;
static char * vc_sasl_authcid = NULL ;
static char * vc_sasl_authzid = NULL ;
static char * vc_sasl_mech = NULL ;
static char * vc_sasl_secprops = NULL ;
# endif
2010-12-15 09:41:30 +08:00
static char * dn = NULL ;
static struct berval cred = { 0 , NULL } ;
void
usage ( void )
{
fprintf ( stderr , _ ( " Issue LDAP Verify Credentials operation to verify a user's credentials \n \n " ) ) ;
2011-01-07 02:37:23 +08:00
fprintf ( stderr , _ ( " usage: %s [options] [DN [cred]]) \n " ) , prog ) ;
2010-12-15 09:41:30 +08:00
fprintf ( stderr , _ ( " where: \n " ) ) ;
fprintf ( stderr , _ ( " DN \t Distinguished Name \n " ) ) ;
fprintf ( stderr , _ ( " cred \t Credentials (prompt if not present) \n " ) ) ;
fprintf ( stderr , _ ( " options: \n " ) ) ;
2011-01-04 06:54:48 +08:00
fprintf ( stderr , _ ( " -a \t Request AuthzId \n " ) ) ;
fprintf ( stderr , _ ( " -b \t Request Password Policy Information \n " ) ) ;
2011-01-07 02:37:23 +08:00
fprintf ( stderr , _ ( " -E sasl=(a[utomatic]|i[nteractive]|q[uiet]> \t SASL mode (defaults to automatic if any other -E option provided, otherwise none)) \n " ) ) ;
fprintf ( stderr , _ ( " -E mech=<mech> \t SASL mechanism (default " " e.g. Simple) \n " ) ) ;
fprintf ( stderr , _ ( " -E realm=<realm> \t SASL Realm (defaults to none) \n " ) ) ;
fprintf ( stderr , _ ( " -E authcid=<authcid> \t SASL Authenication Identity (defaults to USER) \n " ) ) ;
fprintf ( stderr , _ ( " -E authzid=<authzid> \t SASL Authorization Identity (defaults to none) \n " ) ) ;
fprintf ( stderr , _ ( " -E secprops=<secprops> \t SASL Security Properties (defaults to none) \n " ) ) ;
2010-12-15 09:41:30 +08:00
tool_common_usage ( ) ;
exit ( EXIT_FAILURE ) ;
}
2011-01-07 02:37:23 +08:00
const char options [ ] = " abE: "
2010-12-15 09:41:30 +08:00
" d:D:e:h:H:InNO:o:p:QR:U:vVw:WxX:y:Y:Z " ;
int
handle_private_option ( int i )
{
switch ( i ) {
char * control , * cvalue ;
int crit ;
case ' E ' : /* vc extension */
if ( protocol = = LDAP_VERSION2 ) {
fprintf ( stderr , _ ( " %s: -E incompatible with LDAPv%d \n " ) ,
prog , protocol ) ;
exit ( EXIT_FAILURE ) ;
}
/* should be extended to support comma separated list of
* [ ! ] key [ = value ] parameters , e . g . - E ! foo , bar = 567
*/
crit = 0 ;
cvalue = NULL ;
if ( optarg [ 0 ] = = ' ! ' ) {
crit = 1 ;
optarg + + ;
}
control = strdup ( optarg ) ;
if ( ( cvalue = strchr ( control , ' = ' ) ) ! = NULL ) {
* cvalue + + = ' \0 ' ;
}
2011-01-07 02:37:23 +08:00
if ( strcasecmp ( control , " sasl " ) = = 0 ) {
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
if ( vc_sasl ! = LDAP_SASL_NONE ) {
fprintf ( stderr ,
_ ( " SASL option previously specified \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
if ( cvalue = = NULL ) {
fprintf ( stderr ,
_ ( " missing mode in SASL option \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
switch ( * cvalue ) {
case ' a ' :
case ' A ' :
vc_sasl = LDAP_SASL_AUTOMATIC ;
break ;
case ' i ' :
case ' I ' :
vc_sasl = LDAP_SASL_INTERACTIVE ;
break ;
case ' q ' :
case ' Q ' :
vc_sasl = LDAP_SASL_QUIET ;
break ;
default :
fprintf ( stderr ,
_ ( " unknown mode %s in SASL option \n " ) , cvalue ) ;
exit ( EXIT_FAILURE ) ;
}
# else
fprintf ( stderr ,
_ ( " %s: not compiled with SASL support \n " ) , prog ) ;
exit ( EXIT_FAILURE ) ;
# endif
} else if ( strcasecmp ( control , " mech " ) = = 0 ) {
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
if ( vc_sasl_mech ) {
fprintf ( stderr ,
_ ( " SASL mech previously specified \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
if ( cvalue = = NULL ) {
fprintf ( stderr ,
_ ( " missing mech in SASL option \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
vc_sasl_mech = ber_strdup ( cvalue ) ;
# else
# endif
} else if ( strcasecmp ( control , " realm " ) = = 0 ) {
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
if ( vc_sasl_realm ) {
fprintf ( stderr ,
_ ( " SASL realm previously specified \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
if ( cvalue = = NULL ) {
fprintf ( stderr ,
_ ( " missing realm in SASL option \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
vc_sasl_realm = ber_strdup ( cvalue ) ;
# else
fprintf ( stderr ,
_ ( " %s: not compiled with SASL support \n " ) , prog ) ;
exit ( EXIT_FAILURE ) ;
# endif
} else if ( strcasecmp ( control , " authcid " ) = = 0 ) {
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
if ( vc_sasl_authcid ) {
fprintf ( stderr ,
_ ( " SASL authcid previously specified \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
if ( cvalue = = NULL ) {
fprintf ( stderr ,
_ ( " missing authcid in SASL option \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
vc_sasl_authcid = ber_strdup ( cvalue ) ;
# else
fprintf ( stderr ,
_ ( " %s: not compiled with SASL support \n " ) , prog ) ;
exit ( EXIT_FAILURE ) ;
# endif
} else if ( strcasecmp ( control , " authzid " ) = = 0 ) {
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
if ( vc_sasl_authzid ) {
fprintf ( stderr ,
_ ( " SASL authzid previously specified \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
if ( cvalue = = NULL ) {
fprintf ( stderr ,
_ ( " missing authzid in SASL option \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
vc_sasl_authzid = ber_strdup ( cvalue ) ;
# else
fprintf ( stderr ,
_ ( " %s: not compiled with SASL support \n " ) , prog ) ;
exit ( EXIT_FAILURE ) ;
2010-12-15 09:41:30 +08:00
# endif
2011-01-07 02:37:23 +08:00
} else if ( strcasecmp ( control , " secprops " ) = = 0 ) {
# if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
if ( vc_sasl_secprops ) {
fprintf ( stderr ,
_ ( " SASL secprops previously specified \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
if ( cvalue = = NULL ) {
fprintf ( stderr ,
_ ( " missing secprops in SASL option \n " ) ) ;
exit ( EXIT_FAILURE ) ;
}
vc_sasl_secprops = ber_strdup ( cvalue ) ;
# else
fprintf ( stderr ,
_ ( " %s: not compiled with SASL support \n " ) , prog ) ;
exit ( EXIT_FAILURE ) ;
# endif
} else {
fprintf ( stderr , _ ( " Invalid Verify Credentials extension name: %s \n " ) , control ) ;
usage ( ) ;
}
2011-01-04 06:54:48 +08:00
case ' a ' : /* request authzid */
req_authzid + + ;
break ;
case ' b ' : /* request authzid */
req_pp + + ;
break ;
2010-12-15 09:41:30 +08:00
default :
return 0 ;
}
return 1 ;
}
int
main ( int argc , char * argv [ ] )
{
int rc ;
LDAP * ld = NULL ;
char * matcheddn = NULL , * text = NULL , * * refs = NULL ;
2011-01-04 05:49:26 +08:00
int rcode ;
char * diag = NULL ;
2010-12-15 09:41:30 +08:00
struct berval * scookie = NULL ;
struct berval * scred = NULL ;
int id , code = 0 ;
LDAPMessage * res ;
LDAPControl * * ctrls = NULL ;
2011-01-04 06:54:48 +08:00
LDAPControl * * vcctrls = NULL ;
int nvcctrls = 0 ;
2010-12-15 09:41:30 +08:00
tool_init ( TOOL_VC ) ;
prog = lutil_progname ( " ldapvc " , argc , argv ) ;
/* LDAPv3 only */
protocol = LDAP_VERSION3 ;
tool_args ( argc , argv ) ;
2011-01-07 02:37:23 +08:00
if ( argc - optind > 0 ) {
dn = argv [ optind + + ] ;
}
if ( argc - optind > 0 ) {
2011-01-08 20:49:38 +08:00
cred . bv_val = strdup ( argv [ optind + + ] ) ;
2010-12-15 09:41:30 +08:00
cred . bv_len = strlen ( cred . bv_val ) ;
}
2011-01-07 02:37:23 +08:00
if ( argc - optind > 0 ) {
usage ( ) ;
}
if ( dn
# ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
& & ! vc_sasl_mech
# endif
& & ! cred . bv_val )
{
cred . bv_val = strdup ( getpassphrase ( _ ( " User's password: " ) ) ) ;
cred . bv_len = strlen ( cred . bv_val ) ;
}
# ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
if ( vc_sasl_mech & & ( vc_sasl = = LDAP_SASL_NONE ) ) {
vc_sasl = LDAP_SASL_AUTOMATIC ;
}
# endif
2010-12-15 09:41:30 +08:00
ld = tool_conn_setup ( 0 , 0 ) ;
tool_bind ( ld ) ;
if ( dont ) {
rc = LDAP_SUCCESS ;
goto skip ;
}
tool_server_controls ( ld , NULL , 0 ) ;
2011-01-04 06:54:48 +08:00
if ( req_authzid ) {
vcctrls = ( LDAPControl * * ) malloc ( 3 * sizeof ( LDAPControl * ) ) ;
vcctrls [ nvcctrls ] = ( LDAPControl * ) malloc ( sizeof ( LDAPControl ) ) ;
2011-01-04 08:08:12 +08:00
vcctrls [ nvcctrls ] - > ldctl_oid = ldap_strdup ( LDAP_CONTROL_AUTHZID_REQUEST ) ;
2011-01-04 06:54:48 +08:00
vcctrls [ nvcctrls ] - > ldctl_iscritical = 0 ;
vcctrls [ nvcctrls ] - > ldctl_value . bv_val = NULL ;
vcctrls [ nvcctrls ] - > ldctl_value . bv_len = 0 ;
vcctrls [ + + nvcctrls ] = NULL ;
}
if ( req_pp ) {
2011-01-04 08:08:12 +08:00
if ( ! vcctrls ) vcctrls = ( LDAPControl * * ) malloc ( 3 * sizeof ( LDAPControl * ) ) ;
2011-01-04 06:54:48 +08:00
vcctrls [ nvcctrls ] = ( LDAPControl * ) malloc ( sizeof ( LDAPControl ) ) ;
2011-01-04 08:08:12 +08:00
vcctrls [ nvcctrls ] - > ldctl_oid = ldap_strdup ( LDAP_CONTROL_PASSWORDPOLICYREQUEST ) ;
2011-01-04 06:54:48 +08:00
vcctrls [ nvcctrls ] - > ldctl_iscritical = 0 ;
vcctrls [ nvcctrls ] - > ldctl_value . bv_val = NULL ;
vcctrls [ nvcctrls ] - > ldctl_value . bv_len = 0 ;
vcctrls [ + + nvcctrls ] = NULL ;
}
2011-01-07 02:37:23 +08:00
# ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
# ifdef HAVE_CYRUS_SASL
if ( vc_sasl_mech ) {
int msgid ;
void * defaults ;
void * context = NULL ;
const char * rmech = NULL ;
defaults = lutil_sasl_defaults ( ld ,
vc_sasl_mech ,
vc_sasl_realm ,
vc_sasl_authcid ,
cred . bv_val ,
sasl_authz_id ) ;
do {
rc = ldap_verify_credentials_interactive ( ld , dn , vc_sasl_mech ,
vcctrls , NULL , NULL ,
vc_sasl , lutil_sasl_interact , defaults , context ,
res , & rmech , & msgid ) ;
if ( rc ! = LDAP_SASL_BIND_IN_PROGRESS ) break ;
ldap_msgfree ( res ) ;
if ( ldap_result ( ld , msgid , LDAP_MSG_ALL , NULL , & res ) = = - 1 | | ! res ) {
ldap_get_option ( ld , LDAP_OPT_RESULT_CODE , ( void * ) & rc ) ;
ldap_get_option ( ld , LDAP_OPT_DIAGNOSTIC_MESSAGE , ( void * ) & text ) ;
tool_perror ( " ldap_verify_credentials_interactive " , rc , NULL , NULL , text , NULL ) ;
ldap_memfree ( text ) ;
2011-11-20 20:52:40 +08:00
tool_exit ( ld , rc ) ;
2011-01-07 02:37:23 +08:00
}
} while ( rc = = LDAP_SASL_BIND_IN_PROGRESS ) ;
lutil_sasl_freedefs ( defaults ) ;
if ( rc ! = LDAP_SUCCESS ) {
ldap_get_option ( ld , LDAP_OPT_DIAGNOSTIC_MESSAGE , ( void * ) & text ) ;
tool_perror ( " ldap_verify_credentials " , rc , NULL , NULL , text , NULL ) ;
rc = EXIT_FAILURE ;
goto skip ;
}
2010-12-15 09:41:30 +08:00
2011-01-07 02:37:23 +08:00
} else
# endif
# endif
{
rc = ldap_verify_credentials ( ld ,
NULL ,
dn , NULL , cred . bv_val ? & cred : NULL , vcctrls ,
NULL , NULL , & id ) ;
if ( rc ! = LDAP_SUCCESS ) {
ldap_get_option ( ld , LDAP_OPT_DIAGNOSTIC_MESSAGE , ( void * ) & text ) ;
tool_perror ( " ldap_verify_credentials " , rc , NULL , NULL , text , NULL ) ;
rc = EXIT_FAILURE ;
goto skip ;
}
2011-01-04 06:54:48 +08:00
2011-01-07 02:37:23 +08:00
for ( ; ; ) {
struct timeval tv ;
2010-12-15 09:41:30 +08:00
2011-01-07 02:37:23 +08:00
if ( tool_check_abandon ( ld , id ) ) {
2011-11-20 20:52:40 +08:00
tool_exit ( ld , LDAP_CANCELLED ) ;
2011-01-07 02:37:23 +08:00
}
2010-12-15 09:41:30 +08:00
2011-01-07 02:37:23 +08:00
tv . tv_sec = 0 ;
tv . tv_usec = 100000 ;
2010-12-15 09:41:30 +08:00
2011-01-07 02:37:23 +08:00
rc = ldap_result ( ld , LDAP_RES_ANY , LDAP_MSG_ALL , & tv , & res ) ;
if ( rc < 0 ) {
tool_perror ( " ldap_result " , rc , NULL , NULL , NULL , NULL ) ;
2011-11-20 20:52:40 +08:00
tool_exit ( ld , rc ) ;
2011-01-07 02:37:23 +08:00
}
2010-12-15 09:41:30 +08:00
2011-01-07 02:37:23 +08:00
if ( rc ! = 0 ) {
break ;
}
}
2010-12-15 09:41:30 +08:00
}
2011-01-07 02:37:23 +08:00
ldap_controls_free ( vcctrls ) ;
vcctrls = NULL ;
2010-12-15 09:41:30 +08:00
rc = ldap_parse_result ( ld , res ,
& code , & matcheddn , & text , & refs , & ctrls , 0 ) ;
2011-01-07 02:37:23 +08:00
if ( rc = = LDAP_SUCCESS ) rc = code ;
2010-12-15 09:41:30 +08:00
2011-01-07 02:37:23 +08:00
if ( rc ! = LDAP_SUCCESS ) {
2010-12-15 09:41:30 +08:00
tool_perror ( " ldap_parse_result " , rc , NULL , matcheddn , text , refs ) ;
rc = EXIT_FAILURE ;
goto skip ;
}
2011-01-04 06:54:48 +08:00
rc = ldap_parse_verify_credentials ( ld , res , & rcode , & diag , & scookie , & scred , & vcctrls ) ;
2010-12-15 09:41:30 +08:00
ldap_msgfree ( res ) ;
2011-01-07 02:37:23 +08:00
if ( rc ! = LDAP_SUCCESS ) {
2010-12-15 09:41:30 +08:00
tool_perror ( " ldap_parse_verify_credentials " , rc , NULL , NULL , NULL , NULL ) ;
rc = EXIT_FAILURE ;
goto skip ;
}
2011-01-04 07:37:48 +08:00
if ( rcode ! = LDAP_SUCCESS ) {
2011-01-04 05:49:26 +08:00
printf ( _ ( " Failed: %s (%d) \n " ) , ldap_err2string ( rcode ) , rcode ) ;
2010-12-15 09:41:30 +08:00
}
2011-01-04 05:49:26 +08:00
if ( diag & & * diag ) {
printf ( _ ( " Diagnostic: %s \n " ) , diag ) ;
}
2011-01-04 06:54:48 +08:00
if ( vcctrls ) {
tool_print_ctrls ( ld , vcctrls ) ;
}
2011-01-04 05:49:26 +08:00
2010-12-15 09:41:30 +08:00
skip :
2011-06-24 08:10:37 +08:00
if ( verbose | | code ! = LDAP_SUCCESS | |
( matcheddn & & * matcheddn ) | | ( text & & * text ) | | refs | | ctrls )
2010-12-15 09:41:30 +08:00
{
printf ( _ ( " Result: %s (%d) \n " ) , ldap_err2string ( code ) , code ) ;
if ( text & & * text ) {
printf ( _ ( " Additional info: %s \n " ) , text ) ;
}
if ( matcheddn & & * matcheddn ) {
printf ( _ ( " Matched DN: %s \n " ) , matcheddn ) ;
}
if ( refs ) {
int i ;
for ( i = 0 ; refs [ i ] ; i + + ) {
printf ( _ ( " Referral: %s \n " ) , refs [ i ] ) ;
}
}
if ( ctrls ) {
tool_print_ctrls ( ld , ctrls ) ;
ldap_controls_free ( ctrls ) ;
}
}
ber_memfree ( text ) ;
ber_memfree ( matcheddn ) ;
ber_memvfree ( ( void * * ) refs ) ;
ber_bvfree ( scookie ) ;
ber_bvfree ( scred ) ;
2011-01-04 06:05:23 +08:00
ber_memfree ( diag ) ;
2011-01-08 20:49:38 +08:00
free ( cred . bv_val ) ;
2010-12-15 09:41:30 +08:00
/* disconnect from server */
2011-11-20 20:52:40 +08:00
tool_exit ( ld , code = = LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE ) ;
2010-12-15 09:41:30 +08:00
}