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__)
27 static 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 
40 kadm5_ret_t
adb_policy_init(kadm5_server_handle_t handle)41 adb_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 
52 kadm5_ret_t
adb_policy_close(kadm5_server_handle_t handle)53 adb_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 */
61 static char *
reverse(str)62 reverse(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
83 static int
84 lower(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
101 static int
str_check_gecos(gecos,pwstr)102 str_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 ... */
136 kadm5_ret_t
passwd_check(kadm5_server_handle_t handle,char * password,int use_policy,kadm5_policy_ent_t pol,krb5_principal principal)137 passwd_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 
204 void
trunc_name(size_t * len,char ** dots)205 trunc_name(size_t *len, char **dots)
206 {
207     *dots = *len > MAXPRINCLEN ? "..." : "";
208     *len = *len > MAXPRINCLEN ? MAXPRINCLEN : *len;
209 }
210