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