Make krb5_aname_to_localname() use the libheimbase binary search functions
This commit is contained in:
		@@ -111,6 +111,7 @@ dist_libkrb5_la_SOURCES =			\
 | 
				
			|||||||
	acl.c					\
 | 
						acl.c					\
 | 
				
			||||||
	add_et_list.c				\
 | 
						add_et_list.c				\
 | 
				
			||||||
	addr_families.c				\
 | 
						addr_families.c				\
 | 
				
			||||||
 | 
						an2ln_plugin.h				\
 | 
				
			||||||
	aname_to_localname.c			\
 | 
						aname_to_localname.c			\
 | 
				
			||||||
	appdefault.c				\
 | 
						appdefault.c				\
 | 
				
			||||||
	asn1_glue.c				\
 | 
						asn1_glue.c				\
 | 
				
			||||||
@@ -339,7 +340,7 @@ nodist_include_HEADERS = krb5_err.h heim_err.h k524_err.h
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
# XXX use nobase_include_HEADERS = krb5/locate_plugin.h
 | 
					# XXX use nobase_include_HEADERS = krb5/locate_plugin.h
 | 
				
			||||||
krb5dir = $(includedir)/krb5
 | 
					krb5dir = $(includedir)/krb5
 | 
				
			||||||
krb5_HEADERS = locate_plugin.h send_to_kdc_plugin.h ccache_plugin.h
 | 
					krb5_HEADERS = locate_plugin.h send_to_kdc_plugin.h ccache_plugin.h an2ln_plugin.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
build_HEADERZ = \
 | 
					build_HEADERZ = \
 | 
				
			||||||
	$(krb5_HEADERS) \
 | 
						$(krb5_HEADERS) \
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										53
									
								
								lib/krb5/an2ln_plugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								lib/krb5/an2ln_plugin.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Copyright (c) 2006 Kungliga Tekniska Högskolan
 | 
				
			||||||
 | 
					 * (Royal Institute of Technology, Stockholm, Sweden).
 | 
				
			||||||
 | 
					 * All rights reserved.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Redistribution and use in source and binary forms, with or without
 | 
				
			||||||
 | 
					 * modification, are permitted provided that the following conditions
 | 
				
			||||||
 | 
					 * are met:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. Redistributions of source code must retain the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 2. Redistributions in binary form must reproduce the above copyright
 | 
				
			||||||
 | 
					 *    notice, this list of conditions and the following disclaimer in the
 | 
				
			||||||
 | 
					 *    documentation and/or other materials provided with the distribution.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 3. Neither the name of the Institute nor the names of its contributors
 | 
				
			||||||
 | 
					 *    may be used to endorse or promote products derived from this software
 | 
				
			||||||
 | 
					 *    without specific prior written permission.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 | 
				
			||||||
 | 
					 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
				
			||||||
 | 
					 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
				
			||||||
 | 
					 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 | 
				
			||||||
 | 
					 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
				
			||||||
 | 
					 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
				
			||||||
 | 
					 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
				
			||||||
 | 
					 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
				
			||||||
 | 
					 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
				
			||||||
 | 
					 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
				
			||||||
 | 
					 * SUCH DAMAGE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* $Id$ */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef HEIMDAL_KRB5_AN2LN_PLUGIN_H
 | 
				
			||||||
 | 
					#define HEIMDAL_KRB5_AN2LN_PLUGIN_H 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define KRB5_PLUGIN_AN2LN "an2ln"
 | 
				
			||||||
 | 
					#define KRB5_PLUGIN_AN2LN_VERSION_0 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef krb5_error_code (*set_result_f)(void *, const char *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct krb5plugin_an2ln_ftable_desc {
 | 
				
			||||||
 | 
					    int			minor_version;
 | 
				
			||||||
 | 
					    krb5_error_code	(*init)(krb5_context, void **);
 | 
				
			||||||
 | 
					    void		(*fini)(void *);
 | 
				
			||||||
 | 
					    krb5_error_code	(*an2ln)(void *, krb5_context, const char *,
 | 
				
			||||||
 | 
						                         krb5_const_principal, set_result_f, void *);
 | 
				
			||||||
 | 
					} krb5plugin_an2ln_ftable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* HEIMDAL_KRB5_AN2LN_PLUGIN_H */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,20 +32,9 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "krb5_locl.h"
 | 
					#include "krb5_locl.h"
 | 
				
			||||||
 | 
					#include "an2ln_plugin.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define KRB5_PLUGIN_AN2LN "an2ln"
 | 
					/* Default plugin (DB using binary search of sorted text file) follows */
 | 
				
			||||||
#define KRB5_PLUGIN_AN2LN_VERSION_0 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef krb5_error_code (*set_result_f)(void *, const char *);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct krb5plugin_an2ln_ftable_desc {
 | 
					 | 
				
			||||||
    int			minor_version;
 | 
					 | 
				
			||||||
    krb5_error_code	(*init)(krb5_context, void **);
 | 
					 | 
				
			||||||
    void		(*fini)(void *);
 | 
					 | 
				
			||||||
    krb5_error_code	(*an2ln)(void *, krb5_context, krb5_const_principal, set_result_f, void *);
 | 
					 | 
				
			||||||
} krb5plugin_an2ln_ftable;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Default plugin follows */
 | 
					 | 
				
			||||||
static krb5_error_code
 | 
					static krb5_error_code
 | 
				
			||||||
an2ln_def_plug_init(krb5_context context, void **ctx)
 | 
					an2ln_def_plug_init(krb5_context context, void **ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -58,164 +47,75 @@ an2ln_def_plug_fini(void *ctx)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Find a non-quoted new-line */
 | 
					 | 
				
			||||||
static char *
 | 
					 | 
				
			||||||
find_line(char *buf, size_t i, size_t right)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    for (; i < right; i++) {
 | 
					 | 
				
			||||||
	/* Seek a two non-quote char sequence */
 | 
					 | 
				
			||||||
	if (buf[i] != '\\' && (i + 1) < right && buf[i + 1] != '\\') {
 | 
					 | 
				
			||||||
	    /* Seek a non-quoted new-line */
 | 
					 | 
				
			||||||
	    for (i += 1; i < right; i++) {
 | 
					 | 
				
			||||||
		if (buf[i] == '\n')
 | 
					 | 
				
			||||||
		    break;
 | 
					 | 
				
			||||||
		if (buf[i] == '\\' && (i + 1) < right && buf[i + 1] != '\n')
 | 
					 | 
				
			||||||
		    i++; /* skip quoted char */
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    break;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (buf[i] == '\n' && (i + 1) < right)
 | 
					 | 
				
			||||||
	return &buf[i + 1];
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static krb5_error_code
 | 
					static krb5_error_code
 | 
				
			||||||
an2ln_def_plug_an2ln(void *plug_ctx, krb5_context context,
 | 
					an2ln_def_plug_an2ln(void *plug_ctx, krb5_context context,
 | 
				
			||||||
		     krb5_const_principal princ,
 | 
							     const char *rule,
 | 
				
			||||||
 | 
							     krb5_const_principal aname,
 | 
				
			||||||
		     set_result_f set_res_f, void *set_res_ctx)
 | 
							     set_result_f set_res_f, void *set_res_ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    krb5_error_code ret;
 | 
					    krb5_error_code ret;
 | 
				
			||||||
    const char *an2ln_db_fname;
 | 
					    const char *an2ln_db_fname;
 | 
				
			||||||
    char *fdata = NULL;
 | 
					    const char *ext;
 | 
				
			||||||
 | 
					    bsearch_file_handle bfh = NULL;
 | 
				
			||||||
    char *unparsed = NULL;
 | 
					    char *unparsed = NULL;
 | 
				
			||||||
    char *cp;
 | 
					    char *value = NULL;
 | 
				
			||||||
    char *p;
 | 
					 | 
				
			||||||
    char *u;
 | 
					 | 
				
			||||||
    int fd = -1;
 | 
					 | 
				
			||||||
    int cmp;
 | 
					 | 
				
			||||||
    size_t sz, l, r, i, k;
 | 
					 | 
				
			||||||
    struct stat st;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    an2ln_db_fname = krb5_config_get_string(context, NULL, "libdefaults",
 | 
					    if (strncmp(rule, "DB:", strlen("DB:") != 0))
 | 
				
			||||||
				 "aname2lname-text-db", NULL);
 | 
					 | 
				
			||||||
    if (an2ln_db_fname)
 | 
					 | 
				
			||||||
	return KRB5_PLUGIN_NO_HANDLE;
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = krb5_unparse_name(context, princ, &unparsed);
 | 
					    /*
 | 
				
			||||||
 | 
					     * This plugin implements a binary search of a sorted text file
 | 
				
			||||||
 | 
					     * (sorted in the C locale).  We really need to know that the file
 | 
				
			||||||
 | 
					     * is text, so we implement a trivial heuristic: the file name must
 | 
				
			||||||
 | 
					     * end in .txt.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    an2ln_db_fname = &rule[strlen("DB:")];
 | 
				
			||||||
 | 
					    if (!*an2ln_db_fname)
 | 
				
			||||||
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					    if (strlen(an2ln_db_fname) < (strlen(".txt") + 1))
 | 
				
			||||||
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					    ext = strrchr(an2ln_db_fname, '.');
 | 
				
			||||||
 | 
					    if (!ext || strcmp(ext, ".txt") != 0)
 | 
				
			||||||
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = krb5_unparse_name(context, aname, &unparsed);
 | 
				
			||||||
    if (ret)
 | 
					    if (ret)
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fd = open(an2ln_db_fname, O_RDONLY);
 | 
					    ret = __bsearch_file_open(an2ln_db_fname, 0, 0, &bfh, NULL);
 | 
				
			||||||
    if (fd == -1) {
 | 
					    if (ret) {
 | 
				
			||||||
 | 
						krb5_set_error_message(context, ret,
 | 
				
			||||||
 | 
								       N_("Couldn't open aname2lname-text-db", ""));
 | 
				
			||||||
	ret = KRB5_PLUGIN_NO_HANDLE;
 | 
						ret = KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
	goto cleanup;
 | 
						goto cleanup;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (fstat(fd, &st) == -1 || st.st_size == 0) {
 | 
					    /* Binary search; file should be sorted (in C locale) */
 | 
				
			||||||
 | 
					    ret = __bsearch_file(bfh, unparsed, &value, NULL, NULL, NULL);
 | 
				
			||||||
 | 
					    if (ret > 0) {
 | 
				
			||||||
 | 
						krb5_set_error_message(context, ret,
 | 
				
			||||||
 | 
								       N_("Couldn't map principal name to username", ""));
 | 
				
			||||||
	ret = KRB5_PLUGIN_NO_HANDLE;
 | 
						ret = KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
	goto cleanup;
 | 
						goto cleanup;
 | 
				
			||||||
    }
 | 
					    } else if (ret < 0) {
 | 
				
			||||||
 | 
						ret = KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
    /*
 | 
					 | 
				
			||||||
     * This is a dead-simple DB, so simple that we read the whole file
 | 
					 | 
				
			||||||
     * in and do the search in memory.  This means that in 32-bit
 | 
					 | 
				
			||||||
     * processes we can't handle large files.  But this should not be a
 | 
					 | 
				
			||||||
     * large file anyways, else use another plugin.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    sz = (size_t)st.st_size;
 | 
					 | 
				
			||||||
    if (st.st_size != (off_t)sz) {
 | 
					 | 
				
			||||||
	ret = E2BIG;
 | 
					 | 
				
			||||||
	goto cleanup;
 | 
						goto cleanup;
 | 
				
			||||||
    }
 | 
					    } else {
 | 
				
			||||||
 | 
						/* ret == 0 -> found */
 | 
				
			||||||
    fdata = malloc(sz + 1);
 | 
						if (!value || !*value) {
 | 
				
			||||||
    if (fdata == NULL) {
 | 
						    krb5_set_error_message(context, ret,
 | 
				
			||||||
	ret = krb5_enomem(context);
 | 
									   N_("Principal mapped to empty username", ""));
 | 
				
			||||||
	goto cleanup;
 | 
						    ret = KRB5_NO_LOCALNAME;
 | 
				
			||||||
    }
 | 
						    goto cleanup;
 | 
				
			||||||
    if (read(fd, fdata, sz) < sz) {
 | 
					 | 
				
			||||||
	krb5_set_error_message(context, errno, "read: reading aname2lname DB");
 | 
					 | 
				
			||||||
	ret = errno;
 | 
					 | 
				
			||||||
	goto cleanup;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    fdata[sz] = '\0';
 | 
					 | 
				
			||||||
    close(fd);
 | 
					 | 
				
			||||||
    fd = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Binary search; file should be sorted */
 | 
					 | 
				
			||||||
    for (l = 0, r = sz, i = sz >> 1; i > l && i < r; ) {
 | 
					 | 
				
			||||||
	heim_assert(i > 0 && i < sz, "invalid aname2lname db index");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* fdata[i] is likely in the middle of a line; find the next line */
 | 
					 | 
				
			||||||
	cp = find_line(fdata, i, r);
 | 
					 | 
				
			||||||
	if (cp == NULL) {
 | 
					 | 
				
			||||||
	    /*
 | 
					 | 
				
			||||||
	     * No new line found to the right; search to the left then
 | 
					 | 
				
			||||||
	     * (this isn't optimal, but it's simple)
 | 
					 | 
				
			||||||
	     */
 | 
					 | 
				
			||||||
	    r = i;
 | 
					 | 
				
			||||||
	    i = (r - l) >> 1;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	i = cp - fdata;
 | 
					 | 
				
			||||||
	heim_assert(i > l && i < r, "invalid aname2lname db index");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Got a line; check it */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* Search for and split on unquoted whitespace */
 | 
					 | 
				
			||||||
	for (p = &fdata[i], u = NULL, k = i; k < r; k++) {
 | 
					 | 
				
			||||||
	    if (fdata[k] == '\\') {
 | 
					 | 
				
			||||||
		k++;
 | 
					 | 
				
			||||||
		continue;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    /* The one concession to CRLF here */
 | 
					 | 
				
			||||||
	    if (fdata[k] == '\r' || fdata[k] == '\n') {
 | 
					 | 
				
			||||||
		fdata[k] = '\0';
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	    if (isspace(fdata[k])) {
 | 
					 | 
				
			||||||
		fdata[k] = '\0';
 | 
					 | 
				
			||||||
		for (; k < r; k++) {
 | 
					 | 
				
			||||||
		    if (fdata[k] == '\\') {
 | 
					 | 
				
			||||||
			k++;
 | 
					 | 
				
			||||||
			continue;
 | 
					 | 
				
			||||||
		    }
 | 
					 | 
				
			||||||
		    if (fdata[k] == '\n')
 | 
					 | 
				
			||||||
			fdata[k] = '\0';
 | 
					 | 
				
			||||||
		    while (isspace(fdata[k]))
 | 
					 | 
				
			||||||
			k++;
 | 
					 | 
				
			||||||
		    break;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		u = &fdata[k];
 | 
					 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	    }
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmp = strcmp(p, unparsed);
 | 
					 | 
				
			||||||
	if (cmp < 0) {
 | 
					 | 
				
			||||||
	    /* search left */
 | 
					 | 
				
			||||||
	    r = i;
 | 
					 | 
				
			||||||
	    i = (r - l) >> 1;
 | 
					 | 
				
			||||||
	} else if (cmp > 0) {
 | 
					 | 
				
			||||||
	    /* search right */
 | 
					 | 
				
			||||||
	    l = i;
 | 
					 | 
				
			||||||
	    i = (r - l) >> 1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
	    /* match! */
 | 
					 | 
				
			||||||
	    if (u == NULL)
 | 
					 | 
				
			||||||
		ret = KRB5_NO_LOCALNAME;
 | 
					 | 
				
			||||||
	    else
 | 
					 | 
				
			||||||
		ret = set_res_f(set_res_ctx, u);
 | 
					 | 
				
			||||||
	    break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ret = set_res_f(set_res_ctx, value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
cleanup:
 | 
					cleanup:
 | 
				
			||||||
    if (fd != -1)
 | 
					    if (bfh)
 | 
				
			||||||
	close(fd);
 | 
						__bsearch_file_close(&bfh);
 | 
				
			||||||
    free(unparsed);
 | 
					    free(unparsed);
 | 
				
			||||||
    free(fdata);
 | 
					    free(value);
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -226,9 +126,11 @@ krb5plugin_an2ln_ftable an2ln_def_plug = {
 | 
				
			|||||||
    an2ln_def_plug_an2ln,
 | 
					    an2ln_def_plug_an2ln,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Plugin engine code follows */
 | 
				
			||||||
struct plctx {
 | 
					struct plctx {
 | 
				
			||||||
    krb5_const_principal aname;
 | 
					    krb5_const_principal aname;
 | 
				
			||||||
    heim_string_t luser;
 | 
					    heim_string_t luser;
 | 
				
			||||||
 | 
					    const char *rule;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static krb5_error_code KRB5_LIB_CALL
 | 
					static krb5_error_code KRB5_LIB_CALL
 | 
				
			||||||
@@ -251,59 +153,64 @@ plcallback(krb5_context context,
 | 
				
			|||||||
    if (plctx->luser)
 | 
					    if (plctx->luser)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return locate->an2ln(plugctx, context, plctx->aname, set_res, plctx);
 | 
					    return locate->an2ln(plugctx, context, plctx->rule, plctx->aname, set_res, plctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static krb5_error_code
 | 
					static krb5_error_code
 | 
				
			||||||
an2lnplugin(krb5_context context, krb5_const_principal aname, heim_string_t *ures)
 | 
					an2ln_plugin(krb5_context context, const char *rule, krb5_const_principal aname,
 | 
				
			||||||
 | 
						     size_t lnsize, char *lname)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    krb5_error_code ret;
 | 
				
			||||||
    struct plctx ctx;
 | 
					    struct plctx ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ctx.rule = rule;
 | 
				
			||||||
    ctx.aname = aname;
 | 
					    ctx.aname = aname;
 | 
				
			||||||
    ctx.luser = NULL;
 | 
					    ctx.luser = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _krb5_plugin_run_f(context, "krb5", KRB5_PLUGIN_AN2LN,
 | 
					    /*
 | 
				
			||||||
		       KRB5_PLUGIN_AN2LN_VERSION_0,
 | 
					     * Order of plugin invocation is non-deterministic, but there should
 | 
				
			||||||
		       0, &ctx, plcallback);
 | 
					     * really be no more than one plugin that can handle any given kind
 | 
				
			||||||
 | 
					     * rule, so the effect should be deterministic anyways.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    ret = _krb5_plugin_run_f(context, "krb5", KRB5_PLUGIN_AN2LN,
 | 
				
			||||||
 | 
								     KRB5_PLUGIN_AN2LN_VERSION_0, 0, &ctx, plcallback);
 | 
				
			||||||
 | 
					    if (ret != 0) {
 | 
				
			||||||
 | 
						heim_release(ctx.luser);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ctx.luser == NULL)
 | 
					    if (ctx.luser == NULL)
 | 
				
			||||||
	return KRB5_NO_LOCALNAME;
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *ures = ctx.luser;
 | 
					    if (strlcpy(lname, heim_string_get_utf8(ctx.luser), lnsize) >= lnsize)
 | 
				
			||||||
 | 
						ret = KRB5_CONFIG_NOTENUFSPACE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    heim_release(ctx.luser);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
reg_def_plugins_once(void *ctx)
 | 
					reg_def_plugins_once(void *ctx)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    krb5_error_code ret;
 | 
					    krb5_error_code ret;
 | 
				
			||||||
    krb5_context context = ctx;
 | 
					    krb5_context context = ctx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = krb5_plugin_register(context, PLUGIN_TYPE_FUNC,
 | 
					    ret = krb5_plugin_register(context, PLUGIN_TYPE_DATA,
 | 
				
			||||||
			       KRB5_PLUGIN_AN2LN, &an2ln_def_plug);
 | 
								       KRB5_PLUGIN_AN2LN, &an2ln_def_plug);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 | 
					static int
 | 
				
			||||||
krb5_aname_to_localname (krb5_context context,
 | 
					princ_realm_is_default(krb5_context context,
 | 
				
			||||||
			 krb5_const_principal aname,
 | 
							       krb5_const_principal aname)
 | 
				
			||||||
			 size_t lnsize,
 | 
					 | 
				
			||||||
			 char *lname)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    static heim_base_once_t reg_def_plugins = HEIM_BASE_ONCE_INIT;
 | 
					 | 
				
			||||||
    krb5_error_code ret;
 | 
					    krb5_error_code ret;
 | 
				
			||||||
    krb5_realm *lrealms, *r;
 | 
					    krb5_realm *lrealms = NULL;
 | 
				
			||||||
    heim_string_t ures = NULL;
 | 
					    krb5_realm *r;
 | 
				
			||||||
    int valid;
 | 
					    int valid;
 | 
				
			||||||
    size_t len;
 | 
					 | 
				
			||||||
    const char *res;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    heim_base_once_f(®_def_plugins, context, reg_def_plugins_once);
 | 
					    ret = krb5_get_default_realms(context, &lrealms);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    ret = krb5_get_default_realms (context, &lrealms);
 | 
					 | 
				
			||||||
    if (ret)
 | 
					    if (ret)
 | 
				
			||||||
	return ret;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    valid = 0;
 | 
					    valid = 0;
 | 
				
			||||||
    for (r = lrealms; *r != NULL; ++r) {
 | 
					    for (r = lrealms; *r != NULL; ++r) {
 | 
				
			||||||
@@ -313,13 +220,96 @@ krb5_aname_to_localname (krb5_context context,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    krb5_free_host_realm (context, lrealms);
 | 
					    krb5_free_host_realm (context, lrealms);
 | 
				
			||||||
    if (valid == 0)
 | 
					    return valid;
 | 
				
			||||||
	return KRB5_NO_LOCALNAME;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (aname->name.name_string.len == 1)
 | 
					/*
 | 
				
			||||||
 | 
					 * This function implements MIT's auth_to_local_names configuration for
 | 
				
			||||||
 | 
					 * configuration compatibility.  Specifically:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * [realms]
 | 
				
			||||||
 | 
					 *     <realm-name> = {
 | 
				
			||||||
 | 
					 *         auth_to_local_names = {
 | 
				
			||||||
 | 
					 *             <unparsed-principal-name> = <username>
 | 
				
			||||||
 | 
					 *         }
 | 
				
			||||||
 | 
					 *     }
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If multiple usernames are configured then the last one is taken.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The configuration can only be expected to hold a relatively small
 | 
				
			||||||
 | 
					 * number of mappings.  For lots of mappings use a DB.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static krb5_error_code
 | 
				
			||||||
 | 
					an2ln_local_names(krb5_context context,
 | 
				
			||||||
 | 
							  krb5_const_principal aname,
 | 
				
			||||||
 | 
							  size_t lnsize,
 | 
				
			||||||
 | 
							  char *lname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    krb5_error_code ret;
 | 
				
			||||||
 | 
					    char *unparsed;
 | 
				
			||||||
 | 
					    char **values;
 | 
				
			||||||
 | 
					    char *res;
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!princ_realm_is_default(context, aname))
 | 
				
			||||||
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = krb5_unparse_name_flags(context, aname,
 | 
				
			||||||
 | 
									  KRB5_PRINCIPAL_UNPARSE_NO_REALM,
 | 
				
			||||||
 | 
									  &unparsed);
 | 
				
			||||||
 | 
					    if (ret)
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					    values = krb5_config_get_strings(context, NULL, "realms", aname->realm,
 | 
				
			||||||
 | 
									     "auth_to_local_names", unparsed, NULL);
 | 
				
			||||||
 | 
					    free(unparsed);
 | 
				
			||||||
 | 
					    if (!values)
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					    /* Take the last value, just like MIT */
 | 
				
			||||||
 | 
					    for (res = NULL, i = 0; values[i]; i++)
 | 
				
			||||||
 | 
						res = values[i];
 | 
				
			||||||
 | 
					    if (res) {
 | 
				
			||||||
 | 
						ret = 0;
 | 
				
			||||||
 | 
						if (strlcpy(lname, res, lnsize) >= lnsize)
 | 
				
			||||||
 | 
						    ret = KRB5_CONFIG_NOTENUFSPACE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!*res || strcmp(res, ":") == 0)
 | 
				
			||||||
 | 
						    ret = KRB5_NO_LOCALNAME;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    krb5_config_free_strings(values);
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Heimdal's default aname2lname mapping.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static krb5_error_code
 | 
				
			||||||
 | 
					an2ln_default(krb5_context context,
 | 
				
			||||||
 | 
						      int root_princs_ok,
 | 
				
			||||||
 | 
						      krb5_const_principal aname,
 | 
				
			||||||
 | 
						      size_t lnsize, char *lname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    krb5_error_code ret;
 | 
				
			||||||
 | 
					    const char *res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!princ_realm_is_default(context, aname))
 | 
				
			||||||
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (aname->name.name_string.len == 1) {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * One component principal names in default realm -> the one
 | 
				
			||||||
 | 
						 * component is the username.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	res = aname->name.name_string.val[0];
 | 
						res = aname->name.name_string.val[0];
 | 
				
			||||||
    else if (aname->name.name_string.len == 2
 | 
					    } else if (aname->name.name_string.len == 2 &&
 | 
				
			||||||
	     && strcmp (aname->name.name_string.val[1], "root") == 0) {
 | 
						       strcmp (aname->name.name_string.val[1], "root") == 0) {
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Two-component principal names in default realm where the
 | 
				
			||||||
 | 
						 * first component is "root" -> root IFF the principal is in
 | 
				
			||||||
 | 
						 * root's .k5login (or whatever krb5_kuserok() does).
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	krb5_principal rootprinc;
 | 
						krb5_principal rootprinc;
 | 
				
			||||||
	krb5_boolean userok;
 | 
						krb5_boolean userok;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -333,21 +323,91 @@ krb5_aname_to_localname (krb5_context context,
 | 
				
			|||||||
	krb5_free_principal(context, rootprinc);
 | 
						krb5_free_principal(context, rootprinc);
 | 
				
			||||||
	if (!userok)
 | 
						if (!userok)
 | 
				
			||||||
	    return KRB5_NO_LOCALNAME;
 | 
						    return KRB5_NO_LOCALNAME;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
	ret = an2lnplugin(context, aname, &ures);
 | 
						return KRB5_PLUGIN_NO_HANDLE;
 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
	    return ret;
 | 
					 | 
				
			||||||
	res = heim_string_get_utf8(ures);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    len = strlen (res);
 | 
					    if (strlcpy(lname, res, lnsize) >= lnsize)
 | 
				
			||||||
    if (len >= lnsize)
 | 
						return KRB5_CONFIG_NOTENUFSPACE;
 | 
				
			||||||
	return ERANGE;
 | 
					 | 
				
			||||||
    strlcpy (lname, res, lnsize);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (ures)
 | 
					 | 
				
			||||||
	heim_release(ures);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Map a principal name to a local username.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns 0 on success, KRB5_NO_LOCALNAME if no mapping was found, or
 | 
				
			||||||
 | 
					 * some Kerberos or system error.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Inputs:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @context    A krb5_context
 | 
				
			||||||
 | 
					 * @aname      A principal name
 | 
				
			||||||
 | 
					 * @lnsize     The size of the buffer into which the username will be written
 | 
				
			||||||
 | 
					 * @lname      The buffer into which the username will be written
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
 | 
				
			||||||
 | 
					krb5_aname_to_localname(krb5_context context,
 | 
				
			||||||
 | 
								krb5_const_principal aname,
 | 
				
			||||||
 | 
								size_t lnsize,
 | 
				
			||||||
 | 
								char *lname)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    static heim_base_once_t reg_def_plugins = HEIM_BASE_ONCE_INIT;
 | 
				
			||||||
 | 
					    krb5_error_code ret;
 | 
				
			||||||
 | 
					    size_t i;
 | 
				
			||||||
 | 
					    char **rules = NULL;
 | 
				
			||||||
 | 
					    char *rule;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (lnsize)
 | 
				
			||||||
 | 
						lname[0] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    heim_base_once_f(®_def_plugins, context, reg_def_plugins_once);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Try MIT's auth_to_local_names config first */
 | 
				
			||||||
 | 
					    ret = an2ln_local_names(context, aname, lnsize, lname);
 | 
				
			||||||
 | 
					    if (ret != KRB5_PLUGIN_NO_HANDLE)
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rules = krb5_config_get_strings(context, NULL, "realms", aname->realm,
 | 
				
			||||||
 | 
									    "auth_to_local", NULL);
 | 
				
			||||||
 | 
					    if (!rules) {
 | 
				
			||||||
 | 
						/* Heimdal's default rule */
 | 
				
			||||||
 | 
						ret = an2ln_default(context, 1, aname, lnsize, lname);
 | 
				
			||||||
 | 
						if (ret == KRB5_PLUGIN_NO_HANDLE)
 | 
				
			||||||
 | 
						    return KRB5_NO_LOCALNAME;
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* MIT rules */
 | 
				
			||||||
 | 
					    for (ret = KRB5_PLUGIN_NO_HANDLE, i = 0; rules[i]; i++) {
 | 
				
			||||||
 | 
						rule = rules[i];
 | 
				
			||||||
 | 
						if (!*rule || strcmp(rule, "NONE") == 0)
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						else if (strcmp(rule, "HEIMDAL_DEFAULT") == 0)
 | 
				
			||||||
 | 
						    ret = an2ln_default(context, 1, aname, lnsize, lname);
 | 
				
			||||||
 | 
						else if (strcmp(rule, "DEFAULT") == 0)
 | 
				
			||||||
 | 
						    ret = an2ln_default(context, 0, aname, lnsize, lname);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						    /* Let the plugins handle DBs and RULEs and anything else*/
 | 
				
			||||||
 | 
						    ret = an2ln_plugin(context, rule, aname, lnsize, lname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ret == 0 && lnsize && lname[0])
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Note that RULEs and DBs only have white-list functionality,
 | 
				
			||||||
 | 
						 * thus RULEs and DBs that we don't understand we simply ignore.
 | 
				
			||||||
 | 
						 *
 | 
				
			||||||
 | 
						 * This means that plugins that implement black-lists are
 | 
				
			||||||
 | 
						 * dangerous: if a black-list plugin isn't found, the black-list
 | 
				
			||||||
 | 
						 * won't be enforced.  But black-lists are dangerous anyways.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						if (ret != KRB5_PLUGIN_NO_HANDLE)
 | 
				
			||||||
 | 
						    break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (ret == KRB5_PLUGIN_NO_HANDLE)
 | 
				
			||||||
 | 
						ret = KRB5_NO_LOCALNAME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    krb5_config_free_strings(rules);
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -269,8 +269,6 @@ given principal name, and if found the given username will be used, or,
 | 
				
			|||||||
if the username is missing, an error will be returned.  If the file
 | 
					if the username is missing, an error will be returned.  If the file
 | 
				
			||||||
doesn't exist, or if no matching line is found then other plugins will
 | 
					doesn't exist, or if no matching line is found then other plugins will
 | 
				
			||||||
be allowed to run.  Note: large
 | 
					be allowed to run.  Note: large
 | 
				
			||||||
.Va aname2lname-text-db
 | 
					 | 
				
			||||||
files are not supported on small memory systems/processes.
 | 
					 | 
				
			||||||
.It Li name_canon_rules = Va rules
 | 
					.It Li name_canon_rules = Va rules
 | 
				
			||||||
One or more name canonicalization rules.  Each rule consists of one or
 | 
					One or more name canonicalization rules.  Each rule consists of one or
 | 
				
			||||||
more tokens separated by colon (':').  The first token must be a rule
 | 
					more tokens separated by colon (':').  The first token must be a rule
 | 
				
			||||||
@@ -363,6 +361,62 @@ See
 | 
				
			|||||||
.It Li tgs_require_subkey
 | 
					.It Li tgs_require_subkey
 | 
				
			||||||
a boolan variable that defaults to false.
 | 
					a boolan variable that defaults to false.
 | 
				
			||||||
Old DCE secd (pre 1.1) might need this to be true.
 | 
					Old DCE secd (pre 1.1) might need this to be true.
 | 
				
			||||||
 | 
					.It Li auth_to_local_names = {
 | 
				
			||||||
 | 
					.Bl -tag -width "xxx" -offset indent
 | 
				
			||||||
 | 
					.It Va principal_name = Va username
 | 
				
			||||||
 | 
					The given
 | 
				
			||||||
 | 
					.Va principal_name
 | 
				
			||||||
 | 
					will be mapped to the given
 | 
				
			||||||
 | 
					.Va username
 | 
				
			||||||
 | 
					if the
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					is a default realm.
 | 
				
			||||||
 | 
					.El
 | 
				
			||||||
 | 
					.It Li }
 | 
				
			||||||
 | 
					.It Li auth_to_local = HEIMDAL_DEFAULT
 | 
				
			||||||
 | 
					Use the Heimdal default principal to username mapping.
 | 
				
			||||||
 | 
					Applies to principals from the
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					if and only if
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					is a default realm.
 | 
				
			||||||
 | 
					.It Li auth_to_local = DEFAULT
 | 
				
			||||||
 | 
					Use the MIT default principal to username mapping.
 | 
				
			||||||
 | 
					Applies to principals from the
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					if and only if
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					is a default realm.
 | 
				
			||||||
 | 
					.It Li auth_to_local = DB:/path/to/db.txt
 | 
				
			||||||
 | 
					Use a binary search of the given DB.  The DB must be a flat-text
 | 
				
			||||||
 | 
					file sortedf in the "C" locale, with each record being a line
 | 
				
			||||||
 | 
					(separated by either LF or CRLF) consisting of a principal name
 | 
				
			||||||
 | 
					followed by whitespace followed by a username.
 | 
				
			||||||
 | 
					Applies to principals from the
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					if and only if
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					is a default realm.
 | 
				
			||||||
 | 
					.It Li auth_to_local = DB:/path/to/db
 | 
				
			||||||
 | 
					Use the given DB, if there's a plugin for it.
 | 
				
			||||||
 | 
					Applies to principals from the
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					if and only if
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					is a default realm.
 | 
				
			||||||
 | 
					.It Li auth_to_local = RULE:...
 | 
				
			||||||
 | 
					Use the given rule, if there's a plugin for it.
 | 
				
			||||||
 | 
					Applies to principals from the
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					if and only if
 | 
				
			||||||
 | 
					.Va REALM
 | 
				
			||||||
 | 
					is a default realm.
 | 
				
			||||||
 | 
					.It Li auth_to_local = NONE
 | 
				
			||||||
 | 
					No additional principal to username mapping is done. Note that
 | 
				
			||||||
 | 
					.Va auth_to_local_names
 | 
				
			||||||
 | 
					and any preceding
 | 
				
			||||||
 | 
					.Va auth_to_local
 | 
				
			||||||
 | 
					rules have precedence.
 | 
				
			||||||
.El
 | 
					.El
 | 
				
			||||||
.It Li }
 | 
					.It Li }
 | 
				
			||||||
.El
 | 
					.El
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user