1 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
3 * Copyright 2011 PADL Software Pty Ltd.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted only as authorized by the OpenLDAP
10 * A copy of this license is available in the file LICENSE in the
11 * top-level directory of the distribution or, alternatively, at
12 * <http://www.OpenLDAP.org/license.html>.
17 #include <ac/string.h>
21 #include <sasl/sasl.h>
22 #include <gssapi/gssapi.h>
23 #include <gssapi/gssapi_ext.h>
25 #define ACL_BUF_SIZE 1024
27 typedef struct gssattr_t {
28 slap_style_t gssattr_style;
29 struct berval gssattr_name; /* asserted name */
30 struct berval gssattr_value; /* asserted value */
33 static int gssattr_dynacl_destroy( void *priv );
37 struct berval *pat, /* pattern to expand and match against */
38 char *str, /* string to match against pattern */
39 struct berval *dn_matches, /* buffer with $N expansion variables from DN */
40 struct berval *val_matches, /* buffer with $N expansion variables from val */
41 AclRegexMatches *matches /* offsets in buffer for $N expansion variables */
55 gssattr = (gssattr_t *)ch_calloc( 1, sizeof( gssattr_t ) );
57 if ( opts == NULL || opts[0] == '\0' ) {
58 fprintf( stderr, "%s line %d: GSS ACL: no attribute specified.\n",
63 if ( pattern == NULL || pattern[0] == '\0' ) {
64 fprintf( stderr, "%s line %d: GSS ACL: no attribute value specified.\n",
69 gssattr->gssattr_style = style;
71 switch ( gssattr->gssattr_style ) {
74 case ACL_STYLE_EXPAND:
77 fprintf( stderr, "%s line %d: GSS ACL: unsupported style \"%s\".\n",
78 fname, lineno, style_strings[style] );
83 ber_str2bv( opts, 0, 1, &gssattr->gssattr_name );
84 ber_str2bv( pattern, 0, 1, &gssattr->gssattr_value );
86 *privp = (void *)gssattr;
90 (void)gssattr_dynacl_destroy( (void *)gssattr );
96 gssattr_dynacl_unparse(
100 gssattr_t *gssattr = (gssattr_t *)priv;
103 bv->bv_len = STRLENOF( " dynacl/gss/.expand=" ) +
104 gssattr->gssattr_name.bv_len +
105 gssattr->gssattr_value.bv_len;
106 bv->bv_val = ch_malloc( bv->bv_len + 1 );
108 ptr = lutil_strcopy( bv->bv_val, " dynacl/gss/" );
109 ptr = lutil_strncopy( ptr, gssattr->gssattr_name.bv_val,
110 gssattr->gssattr_name.bv_len );
111 switch ( gssattr->gssattr_style ) {
113 ptr = lutil_strcopy( ptr, ".exact=" );
115 case ACL_STYLE_REGEX:
116 ptr = lutil_strcopy( ptr, ".regex=" );
118 case ACL_STYLE_EXPAND:
119 ptr = lutil_strcopy( ptr, ".expand=" );
126 ptr = lutil_strncopy( ptr, gssattr->gssattr_value.bv_val,
127 gssattr->gssattr_value.bv_len );
131 bv->bv_len = ptr - bv->bv_val;
141 AttributeDescription *desc,
145 slap_access_t *grant,
146 slap_access_t *deny )
148 gssattr_t *gssattr = (gssattr_t *)priv;
149 sasl_conn_t *sasl_ctx = op->o_conn->c_sasl_authctx;
150 gss_name_t gss_name = GSS_C_NO_NAME;
151 OM_uint32 major, minor;
153 int authenticated, complete;
154 gss_buffer_desc attr = GSS_C_EMPTY_BUFFER;
157 ACL_INVALIDATE( *deny );
159 if ( sasl_ctx == NULL ||
160 sasl_getprop( sasl_ctx, SASL_GSS_PEER_NAME, (const void **)&gss_name) != 0 ||
161 gss_name == GSS_C_NO_NAME ) {
165 attr.length = gssattr->gssattr_name.bv_len;
166 attr.value = gssattr->gssattr_name.bv_val;
168 while ( more != 0 ) {
169 AclRegexMatches amatches = { 0 };
170 gss_buffer_desc gss_value = GSS_C_EMPTY_BUFFER;
171 gss_buffer_desc gss_display_value = GSS_C_EMPTY_BUFFER;
172 struct berval bv_value;
174 major = gss_get_name_attribute( &minor, gss_name, &attr,
175 &authenticated, &complete,
176 &gss_value, &gss_display_value, &more );
177 if ( GSS_ERROR( major ) ) {
179 } else if ( authenticated == 0 ) {
180 gss_release_buffer( &minor, &gss_value );
181 gss_release_buffer( &minor, &gss_display_value );
185 bv_value.bv_len = gss_value.length;
186 bv_value.bv_val = (char *)gss_value.value;
188 if ( !ber_bvccmp( &gssattr->gssattr_value, '*' ) ) {
189 if ( gssattr->gssattr_style != ACL_STYLE_BASE ) {
190 amatches.dn_count = nmatch;
191 AC_MEMCPY( amatches.dn_data, matches, sizeof( amatches.dn_data ) );
194 switch ( gssattr->gssattr_style ) {
195 case ACL_STYLE_REGEX:
196 /* XXX assumes value NUL terminated */
197 granted = regex_matches( &gssattr->gssattr_value, bv_value.bv_val,
198 &target->e_nname, val, &amatches );
200 case ACL_STYLE_EXPAND: {
202 char buf[ACL_BUF_SIZE];
204 bv.bv_len = sizeof( buf ) - 1;
207 granted = ( acl_string_expand( &bv, &gssattr->gssattr_value,
208 &target->e_nname, val,
209 &amatches ) == 0 ) &&
210 ( ber_bvstrcmp( &bv, &bv_value) == 0 );
214 granted = ( ber_bvstrcmp( &gssattr->gssattr_value, &bv_value ) == 0 );
224 gss_release_buffer( &minor, &gss_value );
225 gss_release_buffer( &minor, &gss_display_value );
233 ACL_LVL_ASSIGN_WRITE( *grant );
240 gssattr_dynacl_destroy(
243 gssattr_t *gssattr = (gssattr_t *)priv;
245 if ( gssattr != NULL ) {
246 if ( !BER_BVISNULL( &gssattr->gssattr_name ) ) {
247 ber_memfree( gssattr->gssattr_name.bv_val );
249 if ( !BER_BVISNULL( &gssattr->gssattr_value ) ) {
250 ber_memfree( gssattr->gssattr_value.bv_val );
258 static struct slap_dynacl_t gssattr_dynacl = {
260 gssattr_dynacl_parse,
261 gssattr_dynacl_unparse,
263 gssattr_dynacl_destroy
267 init_module( int argc, char *argv[] )
269 return slap_dynacl_register( &gssattr_dynacl );
275 struct berval *pat, /* pattern to expand and match against */
276 char *str, /* string to match against pattern */
277 struct berval *dn_matches, /* buffer with $N expansion variables from DN */
278 struct berval *val_matches, /* buffer with $N expansion variables from val */
279 AclRegexMatches *matches /* offsets in buffer for $N expansion variables */
283 char newbuf[ACL_BUF_SIZE];
287 bv.bv_len = sizeof( newbuf ) - 1;
294 acl_string_expand( &bv, pat, dn_matches, val_matches, matches );
295 rc = regcomp( &re, newbuf, REG_EXTENDED|REG_ICASE );
297 char error[ACL_BUF_SIZE];
298 regerror( rc, &re, error, sizeof( error ) );
300 Debug( LDAP_DEBUG_TRACE,
301 "compile( \"%s\", \"%s\") failed %s\n",
302 pat->bv_val, str, error );
306 rc = regexec( &re, str, 0, NULL, 0 );
309 Debug( LDAP_DEBUG_TRACE,
310 "=> regex_matches: string: %s\n", str, 0, 0 );
311 Debug( LDAP_DEBUG_TRACE,
312 "=> regex_matches: rc: %d %s\n",
313 rc, !rc ? "matches" : "no matches", 0 );