1 /* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */
2 /*
3 * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
4 *
5 */
6
7 #include <k5-int.h>
8 #include <gssrpc/rpc.h>
9 #include <gssapi/gssapi_krb5.h> /* for gss_nt_krb5_name */
10 #include <syslog.h>
11 #include <kadm5/kadm_rpc.h>
12 #include <krb5.h>
13 #include <kadm5/admin.h>
14 #include <adm_proto.h>
15 #include "misc.h"
16 #include "kadm5/server_internal.h"
17
18 extern void *global_server_handle;
19
20 static int check_rpcsec_auth(struct svc_req *);
21
22 /*
23 * Function: kadm_1
24 *
25 * Purpose: RPC processing procedure.
26 * originally generated from rpcgen
27 *
28 * Arguments:
29 * rqstp (input) rpc request structure
30 * transp (input) rpc transport structure
31 * (input/output)
32 * <return value>
33 *
34 * Requires:
35 * Effects:
36 * Modifies:
37 */
38
kadm_1(rqstp,transp)39 void kadm_1(rqstp, transp)
40 struct svc_req *rqstp;
41 SVCXPRT *transp;
42 {
43 union {
44 cprinc_arg create_principal_2_arg;
45 dprinc_arg delete_principal_2_arg;
46 mprinc_arg modify_principal_2_arg;
47 rprinc_arg rename_principal_2_arg;
48 gprinc_arg get_principal_2_arg;
49 chpass_arg chpass_principal_2_arg;
50 chrand_arg chrand_principal_2_arg;
51 cpol_arg create_policy_2_arg;
52 dpol_arg delete_policy_2_arg;
53 mpol_arg modify_policy_2_arg;
54 gpol_arg get_policy_2_arg;
55 setkey_arg setkey_principal_2_arg;
56 cprinc3_arg create_principal3_2_arg;
57 chpass3_arg chpass_principal3_2_arg;
58 chrand3_arg chrand_principal3_2_arg;
59 setkey3_arg setkey_principal3_2_arg;
60 setkey4_arg setkey_principal4_2_arg;
61 getpkeys_arg get_principal_keys_2_arg;
62 } argument;
63 union {
64 generic_ret gen_ret;
65 gprinc_ret get_principal_2_ret;
66 chrand_ret chrand_principal_2_ret;
67 gpol_ret get_policy_2_ret;
68 getprivs_ret get_privs_2_ret;
69 gprincs_ret get_princs_2_ret;
70 gpols_ret get_pols_2_ret;
71 chrand_ret chrand_principal3_2_ret;
72 gstrings_ret get_string_2_ret;
73 getpkeys_ret get_principal_keys_ret;
74 } result;
75 bool_t retval;
76 bool_t (*xdr_argument)(), (*xdr_result)();
77 bool_t (*local)();
78
79 if (rqstp->rq_cred.oa_flavor != AUTH_GSSAPI &&
80 !check_rpcsec_auth(rqstp)) {
81 krb5_klog_syslog(LOG_ERR, "Authentication attempt failed: %s, "
82 "RPC authentication flavor %d",
83 client_addr(rqstp->rq_xprt),
84 rqstp->rq_cred.oa_flavor);
85 svcerr_weakauth(transp);
86 return;
87 }
88
89 switch (rqstp->rq_proc) {
90 case NULLPROC:
91 (void) svc_sendreply(transp, xdr_void, (char *)NULL);
92 return;
93
94 case CREATE_PRINCIPAL:
95 xdr_argument = xdr_cprinc_arg;
96 xdr_result = xdr_generic_ret;
97 local = (bool_t (*)()) create_principal_2_svc;
98 break;
99
100 case DELETE_PRINCIPAL:
101 xdr_argument = xdr_dprinc_arg;
102 xdr_result = xdr_generic_ret;
103 local = (bool_t (*)()) delete_principal_2_svc;
104 break;
105
106 case MODIFY_PRINCIPAL:
107 xdr_argument = xdr_mprinc_arg;
108 xdr_result = xdr_generic_ret;
109 local = (bool_t (*)()) modify_principal_2_svc;
110 break;
111
112 case RENAME_PRINCIPAL:
113 xdr_argument = xdr_rprinc_arg;
114 xdr_result = xdr_generic_ret;
115 local = (bool_t (*)()) rename_principal_2_svc;
116 break;
117
118 case GET_PRINCIPAL:
119 xdr_argument = xdr_gprinc_arg;
120 xdr_result = xdr_gprinc_ret;
121 local = (bool_t (*)()) get_principal_2_svc;
122 break;
123
124 case GET_PRINCS:
125 xdr_argument = xdr_gprincs_arg;
126 xdr_result = xdr_gprincs_ret;
127 local = (bool_t (*)()) get_princs_2_svc;
128 break;
129
130 case CHPASS_PRINCIPAL:
131 xdr_argument = xdr_chpass_arg;
132 xdr_result = xdr_generic_ret;
133 local = (bool_t (*)()) chpass_principal_2_svc;
134 break;
135
136 case SETKEY_PRINCIPAL:
137 xdr_argument = xdr_setkey_arg;
138 xdr_result = xdr_generic_ret;
139 local = (bool_t (*)()) setkey_principal_2_svc;
140 break;
141
142 case CHRAND_PRINCIPAL:
143 xdr_argument = xdr_chrand_arg;
144 xdr_result = xdr_chrand_ret;
145 local = (bool_t (*)()) chrand_principal_2_svc;
146 break;
147
148 case CREATE_POLICY:
149 xdr_argument = xdr_cpol_arg;
150 xdr_result = xdr_generic_ret;
151 local = (bool_t (*)()) create_policy_2_svc;
152 break;
153
154 case DELETE_POLICY:
155 xdr_argument = xdr_dpol_arg;
156 xdr_result = xdr_generic_ret;
157 local = (bool_t (*)()) delete_policy_2_svc;
158 break;
159
160 case MODIFY_POLICY:
161 xdr_argument = xdr_mpol_arg;
162 xdr_result = xdr_generic_ret;
163 local = (bool_t (*)()) modify_policy_2_svc;
164 break;
165
166 case GET_POLICY:
167 xdr_argument = xdr_gpol_arg;
168 xdr_result = xdr_gpol_ret;
169 local = (bool_t (*)()) get_policy_2_svc;
170 break;
171
172 case GET_POLS:
173 xdr_argument = xdr_gpols_arg;
174 xdr_result = xdr_gpols_ret;
175 local = (bool_t (*)()) get_pols_2_svc;
176 break;
177
178 case GET_PRIVS:
179 xdr_argument = xdr_u_int32;
180 xdr_result = xdr_getprivs_ret;
181 local = (bool_t (*)()) get_privs_2_svc;
182 break;
183
184 case INIT:
185 xdr_argument = xdr_u_int32;
186 xdr_result = xdr_generic_ret;
187 local = (bool_t (*)()) init_2_svc;
188 break;
189
190 case CREATE_PRINCIPAL3:
191 xdr_argument = xdr_cprinc3_arg;
192 xdr_result = xdr_generic_ret;
193 local = (bool_t (*)()) create_principal3_2_svc;
194 break;
195
196 case CHPASS_PRINCIPAL3:
197 xdr_argument = xdr_chpass3_arg;
198 xdr_result = xdr_generic_ret;
199 local = (bool_t (*)()) chpass_principal3_2_svc;
200 break;
201
202 case CHRAND_PRINCIPAL3:
203 xdr_argument = xdr_chrand3_arg;
204 xdr_result = xdr_chrand_ret;
205 local = (bool_t (*)()) chrand_principal3_2_svc;
206 break;
207
208 case SETKEY_PRINCIPAL3:
209 xdr_argument = xdr_setkey3_arg;
210 xdr_result = xdr_generic_ret;
211 local = (bool_t (*)()) setkey_principal3_2_svc;
212 break;
213
214 case PURGEKEYS:
215 xdr_argument = xdr_purgekeys_arg;
216 xdr_result = xdr_generic_ret;
217 local = (bool_t (*)()) purgekeys_2_svc;
218 break;
219
220 case GET_STRINGS:
221 xdr_argument = xdr_gstrings_arg;
222 xdr_result = xdr_gstrings_ret;
223 local = (bool_t (*)()) get_strings_2_svc;
224 break;
225
226 case SET_STRING:
227 xdr_argument = xdr_sstring_arg;
228 xdr_result = xdr_generic_ret;
229 local = (bool_t (*)()) set_string_2_svc;
230 break;
231
232 case SETKEY_PRINCIPAL4:
233 xdr_argument = xdr_setkey4_arg;
234 xdr_result = xdr_generic_ret;
235 local = (bool_t (*)()) setkey_principal4_2_svc;
236 break;
237
238 case EXTRACT_KEYS:
239 xdr_argument = xdr_getpkeys_arg;
240 xdr_result = xdr_getpkeys_ret;
241 local = (bool_t (*)()) get_principal_keys_2_svc;
242 break;
243
244 default:
245 krb5_klog_syslog(LOG_ERR, "Invalid KADM5 procedure number: %s, %d",
246 client_addr(rqstp->rq_xprt), rqstp->rq_proc);
247 svcerr_noproc(transp);
248 return;
249 }
250 memset(&argument, 0, sizeof(argument));
251 if (!svc_getargs(transp, xdr_argument, &argument)) {
252 svcerr_decode(transp);
253 return;
254 }
255 memset(&result, 0, sizeof(result));
256 retval = (*local)(&argument, &result, rqstp);
257 if (retval && !svc_sendreply(transp, xdr_result, (void *)&result)) {
258 krb5_klog_syslog(LOG_ERR, "WARNING! Unable to send function results, "
259 "continuing.");
260 svcerr_systemerr(transp);
261 }
262 if (!svc_freeargs(transp, xdr_argument, &argument)) {
263 krb5_klog_syslog(LOG_ERR, "WARNING! Unable to free arguments, "
264 "continuing.");
265 }
266 if (!svc_freeargs(transp, xdr_result, &result)) {
267 krb5_klog_syslog(LOG_ERR, "WARNING! Unable to free results, "
268 "continuing.");
269 }
270 return;
271 }
272
273 static int
check_rpcsec_auth(struct svc_req * rqstp)274 check_rpcsec_auth(struct svc_req *rqstp)
275 {
276 gss_ctx_id_t ctx;
277 krb5_context kctx;
278 OM_uint32 maj_stat, min_stat;
279 gss_name_t name;
280 krb5_principal princ;
281 int ret, success;
282 krb5_data *c1, *c2, *realm;
283 gss_buffer_desc gss_str;
284 kadm5_server_handle_t handle;
285 size_t slen;
286 char *sdots;
287
288 success = 0;
289 handle = (kadm5_server_handle_t)global_server_handle;
290
291 if (rqstp->rq_cred.oa_flavor != RPCSEC_GSS)
292 return 0;
293
294 ctx = rqstp->rq_svccred;
295
296 maj_stat = gss_inquire_context(&min_stat, ctx, NULL, &name,
297 NULL, NULL, NULL, NULL, NULL);
298 if (maj_stat != GSS_S_COMPLETE) {
299 krb5_klog_syslog(LOG_ERR, _("check_rpcsec_auth: failed "
300 "inquire_context, stat=%u"), maj_stat);
301 log_badauth(maj_stat, min_stat, rqstp->rq_xprt, NULL);
302 goto fail_name;
303 }
304
305 kctx = handle->context;
306 ret = gss_to_krb5_name_1(rqstp, kctx, name, &princ, &gss_str);
307 if (ret == 0)
308 goto fail_name;
309
310 slen = gss_str.length;
311 trunc_name(&slen, &sdots);
312 /*
313 * Since we accept with GSS_C_NO_NAME, the client can authenticate
314 * against the entire kdb. Therefore, ensure that the service
315 * name is something reasonable.
316 */
317 if (krb5_princ_size(kctx, princ) != 2)
318 goto fail_princ;
319
320 c1 = krb5_princ_component(kctx, princ, 0);
321 c2 = krb5_princ_component(kctx, princ, 1);
322 realm = krb5_princ_realm(kctx, princ);
323 success = data_eq_string(*realm, handle->params.realm) &&
324 data_eq_string(*c1, "kadmin") && !data_eq_string(*c2, "history");
325
326 fail_princ:
327 if (!success) {
328 krb5_klog_syslog(LOG_ERR, _("bad service principal %.*s%s"),
329 (int) slen, (char *) gss_str.value, sdots);
330 }
331 gss_release_buffer(&min_stat, &gss_str);
332 krb5_free_principal(kctx, princ);
333 fail_name:
334 gss_release_name(&min_stat, &name);
335 return success;
336 }
337
338 int
gss_to_krb5_name_1(struct svc_req * rqstp,krb5_context ctx,gss_name_t gss_name,krb5_principal * princ,gss_buffer_t gss_str)339 gss_to_krb5_name_1(struct svc_req *rqstp, krb5_context ctx, gss_name_t gss_name,
340 krb5_principal *princ, gss_buffer_t gss_str)
341 {
342 OM_uint32 status, minor_stat;
343 gss_OID gss_type;
344 char *str;
345 int success;
346
347 status = gss_display_name(&minor_stat, gss_name, gss_str, &gss_type);
348 if ((status != GSS_S_COMPLETE) || (gss_type != gss_nt_krb5_name)) {
349 krb5_klog_syslog(LOG_ERR, _("gss_to_krb5_name: failed display_name "
350 "status %d"), status);
351 log_badauth(status, minor_stat, rqstp->rq_xprt, NULL);
352 return 0;
353 }
354 str = malloc(gss_str->length +1);
355 if (str == NULL)
356 return 0;
357 *str = '\0';
358
359 strncat(str, gss_str->value, gss_str->length);
360 success = (krb5_parse_name(ctx, str, princ) == 0);
361 free(str);
362 return success;
363 }
364