From 3ea436891367ac3f8ad41fd2572b59fe7d0a27af Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Tue, 13 Apr 2004 17:18:03 +0000 Subject: [PATCH] add slapsaslauth test tool --- doc/man/man8/slapsaslauth.8 | 103 +++++++++++++++++++++ servers/slapd/main.c | 3 +- servers/slapd/slapcommon.c | 38 ++++++-- servers/slapd/slapcommon.h | 5 + servers/slapd/slapdn.c | 3 +- servers/slapd/slapsaslauth.c | 173 +++++++++++++++++++++++++++++++++++ 6 files changed, 316 insertions(+), 9 deletions(-) create mode 100644 doc/man/man8/slapsaslauth.8 create mode 100644 servers/slapd/slapsaslauth.c diff --git a/doc/man/man8/slapsaslauth.8 b/doc/man/man8/slapsaslauth.8 new file mode 100644 index 0000000000..545074612b --- /dev/null +++ b/doc/man/man8/slapsaslauth.8 @@ -0,0 +1,103 @@ +.TH SLAPSASLAUTH 8C "RELEASEDATE" "OpenLDAP LDVERSION" +.\" Copyright 2004 The OpenLDAP Foundation All Rights Reserved. +.\" Copying restrictions apply. See COPYRIGHT/LICENSE. +.SH NAME +slapsaslauth \- Check a list of string-represented IDs for authc/authz. +.SH SYNOPSIS +.B SBINDIR/slapsaslauth +.B [\-v] +.B [\-d level] +.B [\-f slapd.conf] +.B [\-U authcID] +.B [\-X authzID] +.B ID [...] +.LP +.SH DESCRIPTION +.LP +.B Slapsaslauth +is used to check the behavior of the slapd in mapping identities +for authentication and authorization purposes, as specified in +.BR slapd.conf (5). +It opens the +.BR slapd.conf (5) +configuration file, reads in the +.B sasl-authz-policy +and +.B sasl-regexp +directives, and then parses the +.B ID +list given on the command-line. +.LP +.SH OPTIONS +.TP +.B \-v +enable verbose mode. +.TP +.BI \-d " level" +enable debugging messages as defined by the specified +.IR level . +.TP +.BI \-f " slapd.conf" +specify an alternative +.BR slapd.conf (5) +file. +.TP +.BI \-U " authcID" +specify an ID to be used as +.I authcID +throughout the test session. +If present, and if no +.B authzID +is given, the IDs in the ID list are treated as +.BR authzID . +.TP +.BI \-X " authzID" +specify an ID to be used as +.I authzID +throughout the test session. +If present, and if no +.B authcID +is given, the IDs in the ID list are treated as +.BR authcID . +If both +.I authcID +and +.I authzID +are given via command line switch, the ID list cannot be present. +.SH EXAMPLES +The command +.LP +.nf +.ft tt + SBINDIR/slapsaslauth -f /ETCDIR/slapd.conf -v \\ + -U bjorn -X u:bjensen + +.ft +.fi +tests whether the user +.I bjorn +can assume the identity of the user +.I bjensen +provided the directives +.LP +.nf +.ft tt + sasl-authz-policy from + sasl-regexp "^uid=([^,]+).*,cn=auth$" + "ldap:///o=University of Michigan,c=US??sub?uid=$1" + +.ft +.fi +are defined in +.BR slapd.conf (5). +.SH "SEE ALSO" +.BR ldap (3), +.BR slapd (8) +.BR slaptest (8) +.LP +"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/) +.SH ACKNOWLEDGEMENTS +.B OpenLDAP +is developed and maintained by The OpenLDAP Project (http://www.openldap.org/). +.B OpenLDAP +is derived from University of Michigan LDAP 3.3 Release. diff --git a/servers/slapd/main.c b/servers/slapd/main.c index 528867ba00..d5cff55b12 100644 --- a/servers/slapd/main.c +++ b/servers/slapd/main.c @@ -65,7 +65,7 @@ static struct sockaddr_in bind_addr; #endif typedef int (MainFunc) LDAP_P(( int argc, char *argv[] )); -extern MainFunc slapadd, slapcat, slapdn, slapindex, slappasswd, slaptest; +extern MainFunc slapadd, slapcat, slapdn, slapindex, slappasswd, slaptest, slapsaslauth; static struct { char *name; @@ -77,6 +77,7 @@ static struct { {"slapindex", slapindex}, {"slappasswd", slappasswd}, {"slaptest", slaptest}, + {"slapsaslauth", slapsaslauth}, {NULL, NULL} }; diff --git a/servers/slapd/slapcommon.c b/servers/slapd/slapcommon.c index a04be91af6..a3cbc72507 100644 --- a/servers/slapd/slapcommon.c +++ b/servers/slapd/slapcommon.c @@ -69,6 +69,10 @@ usage( int tool, const char *progname ) case SLAPINDEX: options = "\t[-n databasenumber | -b suffix]\n"; break; + + case SLAPSASLAUTH: + options = "\t[-U authcID] [-X authzID] ID [...]\n"; + break; } if ( options != NULL ) { @@ -102,7 +106,7 @@ slap_tool_init( int truncatemode = 0; #ifdef CSRIMALLOC - leakfilename = malloc( strlen( progname ) + sizeof(".leak") ); + leakfilename = malloc( strlen( progname ) + STRLEOF( ".leak" ) - 1 ); sprintf( leakfilename, "%s.leak", progname ); if( ( leakfile = fopen( leakfilename, "w" )) == NULL ) { leakfile = stderr; @@ -125,6 +129,10 @@ slap_tool_init( options = "d:f:v"; break; + case SLAPSASLAUTH: + options = "d:f:U:vX:"; + break; + case SLAPINDEX: options = "b:cd:f:n:v"; mode |= SLAP_TOOL_READMAIN; @@ -140,8 +148,7 @@ slap_tool_init( while ( (i = getopt( argc, argv, options )) != EOF ) { switch ( i ) { case 'b': - base.bv_val = strdup( optarg ); - base.bv_len = strlen( base.bv_val ); + ber_str2bv( optarg, 0, 1, &base ); break; case 'c': /* enable continue mode */ @@ -210,6 +217,10 @@ slap_tool_init( mode |= SLAP_TRUNCATE_MODE; break; + case 'U': + ber_str2bv( optarg, 0, 0, &authcID ); + break; + case 'u': /* dry run */ dryrun++; break; @@ -227,6 +238,10 @@ slap_tool_init( update_ctxcsn = SLAP_TOOL_CTXCSN_BATCH; break; + case 'X': + ber_str2bv( optarg, 0, 0, &authzID ); + break; + default: usage( tool, progname ); break; @@ -257,6 +272,12 @@ slap_tool_init( } break; + case SLAPSASLAUTH: + if ( argc == optind && BER_BVISNULL( &authcID ) ) { + usage( tool, progname ); + } + break; + case SLAPTEST: if ( argc != optind ) { usage( tool, progname ); @@ -350,21 +371,24 @@ slap_tool_init( case SLAPTEST: return; + case SLAPSASLAUTH: + be = NULL; + goto startup; + default: break; } if( subtree ) { struct berval val; - val.bv_val = subtree; - val.bv_len = strlen( subtree ); + ber_str2bv( subtree, 0, 0, &val ); rc = dnNormalize( 0, NULL, NULL, &val, &sub_ndn, NULL ); if( rc != LDAP_SUCCESS ) { fprintf( stderr, "Invalid subtree DN '%s'\n", optarg ); exit( EXIT_FAILURE ); } - if( base.bv_val == NULL && dbnum == -1 ) + if ( BER_BVISNULL( &base ) && dbnum == -1 ) base = val; else free( subtree ); @@ -444,6 +468,8 @@ slap_tool_init( be = &backends[dbnum]; } +startup:; + #ifdef CSRIMALLOC mal_leaktrace(1); #endif diff --git a/servers/slapd/slapcommon.h b/servers/slapd/slapcommon.h index 12a1b57ffd..3722fb603d 100644 --- a/servers/slapd/slapcommon.h +++ b/servers/slapd/slapcommon.h @@ -27,6 +27,7 @@ enum slaptool { SLAPINDEX, /* database index tool */ SLAPPASSWD, /* password generation tool */ SLAPTEST, /* slapd.conf test tool */ + SLAPSASLAUTH, /* test sasl-regexp and authc/authz stuff */ SLAPLAST }; @@ -50,6 +51,8 @@ typedef struct tool_vars { int tv_dryrun; struct berval tv_sub_ndn; FILE *tv_ldiffp; + struct berval tv_authcID; + struct berval tv_authzID; } tool_vars; extern tool_vars tool_globals; @@ -69,6 +72,8 @@ extern tool_vars tool_globals; #define dryrun tool_globals.tv_dryrun #define sub_ndn tool_globals.tv_sub_ndn #define ldiffp tool_globals.tv_ldiffp +#define authcID tool_globals.tv_authcID +#define authzID tool_globals.tv_authzID void slap_tool_init LDAP_P(( const char* name, diff --git a/servers/slapd/slapdn.c b/servers/slapd/slapdn.c index 3db6e0be1f..7eb4b823cd 100644 --- a/servers/slapd/slapdn.c +++ b/servers/slapd/slapdn.c @@ -51,8 +51,7 @@ slapdn( int argc, char **argv ) for ( ; argc--; argv++ ) { struct berval dn, pdn, ndn; - dn.bv_val = argv[ 0 ]; - dn.bv_len = strlen( argv[ 0 ] ); + ber_str2bv( argv[ 0 ], 0, 0, &dn ); rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, NULL ); diff --git a/servers/slapd/slapsaslauth.c b/servers/slapd/slapsaslauth.c new file mode 100644 index 0000000000..baa9236c3f --- /dev/null +++ b/servers/slapd/slapsaslauth.c @@ -0,0 +1,173 @@ +/* This work is part of OpenLDAP Software . + * + * Copyright 2004 The OpenLDAP Foundation. + * Portions Copyright 2004 Pierangelo Masarati. + * 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 file LICENSE in the + * top-level directory of the distribution or, alternatively, at + * . + */ +/* ACKNOWLEDGEMENTS: + * This work was initially developed by Pierangelo Masarati for inclusion + * in OpenLDAP Software. + */ + +#include "portable.h" + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "slapcommon.h" + +static int +do_check( Connection *c, Operation *op, struct berval *id ) +{ + struct berval authcDN; + int rc; + + rc = slap_sasl_getdn( c, op, id, NULL, &authcDN, SLAP_GETDN_AUTHCID ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "ID: <%s> check failed %d (%s)\n", + id->bv_val, rc, + ldap_err2string( rc ) ); + rc = 1; + + } else { + if ( !BER_BVISNULL( &authzID ) ) { + rc = slap_sasl_authorized( op, &authcDN, &authzID ); + + fprintf( stderr, + "ID: <%s>\n" + "authcDN: <%s>\n" + "authzDN: <%s>\n" + "authorization %s\n", + id->bv_val, + authcDN.bv_val, + authzID.bv_val, + rc == LDAP_SUCCESS ? "OK" : "failed" ); + + } else { + fprintf( stderr, "ID: <%s> check succeeded\n" + "authcID: <%s>\n", + id->bv_val, + authcDN.bv_val ); + op->o_tmpfree( authcDN.bv_val, op->o_tmpmemctx ); + } + rc = 0; + } + + return rc; +} + +int +slapsaslauth( int argc, char **argv ) +{ + int rc = EXIT_SUCCESS; + const char *progname = "slapsaslauth"; + Connection conn; + Operation op; + +#ifdef NEW_LOGGING + lutil_log_initialize( argc, argv ); +#endif + slap_tool_init( progname, SLAPSASLAUTH, argc, argv ); + + argv = &argv[ optind ]; + argc -= optind; + + memset( &conn, 0, sizeof( Connection ) ); + memset( &op, 0, sizeof( Operation ) ); + + connection_fake_init( &conn, &op, &conn ); + + if ( !BER_BVISNULL( &authzID ) ) { + struct berval authzDN; + + rc = slap_sasl_getdn( &conn, &op, &authzID, NULL, &authzDN, + SLAP_GETDN_AUTHZID ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "authzID: <%s> check failed %d (%s)\n", + authzID.bv_val, rc, + ldap_err2string( rc ) ); + rc = 1; + BER_BVZERO( &authzID ); + goto destroy; + } + + authzID = authzDN; + } + + + if ( !BER_BVISNULL( &authcID ) ) { + if ( !BER_BVISNULL( &authzID ) || argc == 0 ) { + rc = do_check( &conn, &op, &authcID ); + goto destroy; + } + + for ( ; argc--; argv++ ) { + struct berval authzDN; + + ber_str2bv( argv[ 0 ], 0, 0, &authzID ); + + rc = slap_sasl_getdn( &conn, &op, &authzID, NULL, &authzDN, + SLAP_GETDN_AUTHZID ); + if ( rc != LDAP_SUCCESS ) { + fprintf( stderr, "authzID: <%s> check failed %d (%s)\n", + authzID.bv_val, rc, + ldap_err2string( rc ) ); + rc = 1; + BER_BVZERO( &authzID ); + goto destroy; + } + + authzID = authzDN; + + rc = do_check( &conn, &op, &authcID ); + + op.o_tmpfree( authzID.bv_val, op.o_tmpmemctx ); + BER_BVZERO( &authzID ); + + if ( rc ) { + goto destroy; + } + } + + goto destroy; + } + + for ( ; argc--; argv++ ) { + struct berval id; + + ber_str2bv( argv[ 0 ], 0, 0, &id ); + + rc = do_check( &conn, &op, &id ); + + if ( rc ) { + goto destroy; + } + } + +destroy:; + if ( !BER_BVISNULL( &authzID ) ) { + op.o_tmpfree( authzID.bv_val, op.o_tmpmemctx ); + } + slap_tool_destroy(); + + return rc; +} +