1
2/*
3 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
4 *
5 *	Openvision retains the copyright to derivative works of
6 *	this source code.  Do *NOT* create a derivative of this
7 *	source code before consulting with your legal department.
8 *	Do *NOT* integrate *ANY* of this source code into another
9 *	product before consulting with your legal department.
10 *
11 *	For further information, read the top-level Openvision
12 *	copyright which is contained in the top-level MIT Kerberos
13 *	copyright.
14 *
15 * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
16 *
17 */
18
19
20/*
21 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
22 *
23 * $Header$
24 */
25
26#if !defined(lint) && !defined(__CODECENTER__)
27static char *rcsid = "$Header$";
28#endif
29
30#include    "k5-int.h"
31#include    <krb5/kdb.h>
32#include    <ctype.h>
33#include    <pwd.h>
34
35/* for strcasecmp */
36#include    <string.h>
37
38#include    "server_internal.h"
39
40kadm5_ret_t
41adb_policy_init(kadm5_server_handle_t handle)
42{
43    /* now policy is initialized as part of database. No seperate call needed */
44    /* Solaris Kerberos: krb5_db_inited returns 0 when db has been inited */
45    if( krb5_db_inited( handle->context ) == 0 )
46	return KADM5_OK;
47
48    return krb5_db_open( handle->context, NULL,
49			 KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN );
50}
51
52kadm5_ret_t
53adb_policy_close(kadm5_server_handle_t handle)
54{
55    /* will be taken care by database close */
56    return KADM5_OK;
57}
58
59#ifdef HESIOD
60/* stolen from v4sever/kadm_funcs.c */
61static char *
62reverse(str)
63	char	*str;
64{
65	static char newstr[80];
66	char	*p, *q;
67	int	i;
68
69	i = strlen(str);
70	if (i >= sizeof(newstr))
71		i = sizeof(newstr)-1;
72	p = str+i-1;
73	q = newstr;
74	q[i]='\0';
75	for(; i > 0; i--)
76		*q++ = *p--;
77
78	return(newstr);
79}
80#endif /* HESIOD */
81
82#if 0
83static int
84lower(str)
85	char	*str;
86{
87	register char	*cp;
88	int	effect=0;
89
90	for (cp = str; *cp; cp++) {
91		if (isupper(*cp)) {
92			*cp = tolower(*cp);
93			effect++;
94		}
95	}
96	return(effect);
97}
98#endif
99
100#ifdef HESIOD
101static int
102str_check_gecos(gecos, pwstr)
103	char	*gecos;
104	char	*pwstr;
105{
106	char		*cp, *ncp, *tcp;
107
108	for (cp = gecos; *cp; ) {
109		/* Skip past punctuation */
110		for (; *cp; cp++)
111			if (isalnum(*cp))
112				break;
113		/* Skip to the end of the word */
114		for (ncp = cp; *ncp; ncp++)
115			if (!isalnum(*ncp) && *ncp != '\'')
116				break;
117		/* Delimit end of word */
118		if (*ncp)
119			*ncp++ = '\0';
120		/* Check word to see if it's the password */
121		if (*cp) {
122			if (!strcasecmp(pwstr, cp))
123				return 1;
124			tcp = reverse(cp);
125			if (!strcasecmp(pwstr, tcp))
126				return 1;
127			cp = ncp;
128		} else
129			break;
130	}
131	return 0;
132}
133#endif /* HESIOD */
134
135/* some of this is stolen from gatekeeper ... */
136kadm5_ret_t
137passwd_check(kadm5_server_handle_t handle,
138	     char *password, int use_policy, kadm5_policy_ent_t pol,
139	     krb5_principal principal)
140{
141    int	    nupper = 0,
142	    nlower = 0,
143	    ndigit = 0,
144	    npunct = 0,
145	    nspec = 0;
146    char    c, *s, *cp;
147#ifdef HESIOD
148    extern  struct passwd *hes_getpwnam();
149    struct  passwd *ent;
150#endif
151
152    if(use_policy) {
153	if(strlen(password) < pol->pw_min_length)
154	    return KADM5_PASS_Q_TOOSHORT;
155	s = password;
156	while ((c = *s++)) {
157	    if (islower((unsigned char) c)) {
158		nlower = 1;
159		continue;
160	    }
161	    else if (isupper((unsigned char) c)) {
162		nupper = 1;
163		continue;
164	    } else if (isdigit((unsigned char) c)) {
165		ndigit = 1;
166		continue;
167	    } else if (ispunct((unsigned char) c)) {
168		npunct = 1;
169		continue;
170	    } else {
171		nspec = 1;
172		continue;
173	    }
174	}
175	if ((nupper + nlower + ndigit + npunct + nspec) < pol->pw_min_classes)
176	    return KADM5_PASS_Q_CLASS;
177	if((find_word(password) == KADM5_OK))
178	    return KADM5_PASS_Q_DICT;
179	else {
180	    int	i, n = krb5_princ_size(handle->context, principal);
181	    cp = krb5_princ_realm(handle->context, principal)->data;
182	    if (strcasecmp(cp, password) == 0)
183		return KADM5_PASS_Q_DICT;
184	    for (i = 0; i < n ; i++) {
185		cp = krb5_princ_component(handle->context, principal, i)->data;
186		if (strcasecmp(cp, password) == 0)
187		    return KADM5_PASS_Q_DICT;
188#ifdef HESIOD
189		ent = hes_getpwnam(cp);
190		if (ent && ent->pw_gecos)
191		    if (str_check_gecos(ent->pw_gecos, password))
192			return KADM5_PASS_Q_DICT; /* XXX new error code? */
193#endif
194	    }
195	    return KADM5_OK;
196	}
197    } else {
198	if (strlen(password) < 1)
199	    return KADM5_PASS_Q_TOOSHORT;
200    }
201    return KADM5_OK;
202}
203
204void
205trunc_name(size_t *len, char **dots)
206{
207    *dots = *len > MAXPRINCLEN ? "..." : "";
208    *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len;
209}
210