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 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 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 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