[11760] | 1 | /* |
---|
| 2 | * kadm_cli_wrap.c |
---|
| 3 | * |
---|
| 4 | * Copyright 1988 by the Massachusetts Institute of Technology. |
---|
| 5 | * |
---|
| 6 | * For copying and distribution information, please see the file |
---|
| 7 | * <mit-copyright.h>. |
---|
| 8 | * |
---|
| 9 | * Kerberos administration server client-side routines |
---|
| 10 | * The client side wrapping of the calls to the admin server. |
---|
| 11 | */ |
---|
| 12 | |
---|
| 13 | #include <mit-copyright.h> |
---|
| 14 | |
---|
| 15 | #include <string.h> |
---|
| 16 | |
---|
| 17 | #define DEFINE_SOCKADDR /* Ask krb.h for struct sockaddr, netdb, etc */ |
---|
| 18 | #include "krb.h" |
---|
| 19 | |
---|
| 20 | #include <kadm.h> |
---|
| 21 | #include <kadm_err.h> |
---|
| 22 | #include <krb_err.h> |
---|
| 23 | #include <krbports.h> |
---|
| 24 | |
---|
| 25 | #ifndef NULL |
---|
| 26 | #define NULL 0 |
---|
| 27 | #endif |
---|
| 28 | |
---|
| 29 | #ifndef KRB_INT32 |
---|
| 30 | #define KRB_INT32 KRB4_32 |
---|
| 31 | #endif |
---|
| 32 | |
---|
| 33 | Kadm_Client client_parm; |
---|
| 34 | int default_client_port = 1; |
---|
| 35 | |
---|
| 36 | /* Macros for use in returning data... used in kadm_cli_send */ |
---|
| 37 | #define RET_N_FREE(r) {clear_secrets(); free((char *)act_st); free((char *)priv_pak); return r;} |
---|
| 38 | |
---|
| 39 | /* Keys for use in the transactions */ |
---|
| 40 | static des_cblock sess_key; /* to be filled in by kadm_cli_keyd */ |
---|
| 41 | static Key_schedule sess_sched; |
---|
| 42 | |
---|
| 43 | static void |
---|
| 44 | clear_secrets() |
---|
| 45 | { |
---|
| 46 | memset((char *)sess_key, 0, sizeof(sess_key)); |
---|
| 47 | memset((char *)sess_sched, 0, sizeof(sess_sched)); |
---|
| 48 | return; |
---|
| 49 | } |
---|
| 50 | |
---|
| 51 | /* |
---|
| 52 | * kadm_init_link |
---|
| 53 | * receives : name, inst, realm |
---|
| 54 | * |
---|
| 55 | * initializes client parm, the Kadm_Client structure which holds the |
---|
| 56 | * data about the connection between the server and client, the services |
---|
| 57 | * used, the locations and other fun things |
---|
| 58 | */ |
---|
[13755] | 59 | int |
---|
[11760] | 60 | kadm_init_link(n, i, r) |
---|
| 61 | char n[]; |
---|
| 62 | char i[]; |
---|
| 63 | char r[]; |
---|
| 64 | { |
---|
| 65 | struct servent *sep; /* service we will talk to */ |
---|
| 66 | u_short sep_port; |
---|
| 67 | struct hostent *hop; /* host we will talk to */ |
---|
| 68 | char adm_hostname[MAXHOSTNAMELEN]; |
---|
| 69 | char *scol = 0; |
---|
| 70 | |
---|
| 71 | #ifdef GLOBAL_ERROR_HANDLING |
---|
| 72 | (void) init_kadm_err_tbl(); |
---|
| 73 | (void) init_krb_err_tbl(); |
---|
| 74 | #endif |
---|
| 75 | |
---|
| 76 | (void) strcpy(client_parm.sname, n); |
---|
| 77 | (void) strcpy(client_parm.sinst, i); |
---|
| 78 | (void) strcpy(client_parm.krbrlm, r); |
---|
| 79 | client_parm.admin_fd = -1; |
---|
| 80 | |
---|
| 81 | /* set up the admin_addr - fetch name of admin host */ |
---|
| 82 | if (krb_get_admhst(adm_hostname, client_parm.krbrlm, 1) != KSUCCESS) |
---|
| 83 | return KADM_NO_HOST; |
---|
| 84 | scol = strchr(adm_hostname,':'); |
---|
| 85 | if (scol) *scol = 0; |
---|
| 86 | if ((hop = gethostbyname(adm_hostname)) == NULL) |
---|
| 87 | return KADM_UNK_HOST; /* couldnt find the admin servers |
---|
| 88 | * address */ |
---|
| 89 | if (scol) { |
---|
| 90 | sep_port = htons(atoi(scol+1)+1); |
---|
| 91 | default_client_port = 0; |
---|
| 92 | } |
---|
| 93 | else if (sep = getservbyname(KADM_SNAME, "tcp")) |
---|
| 94 | sep_port = sep->s_port; |
---|
| 95 | else |
---|
| 96 | sep_port = htons(KADM_PORT); /* KADM_SNAME = kerberos_master/tcp */ |
---|
| 97 | memset((char *) &client_parm.admin_addr, 0, |
---|
| 98 | sizeof(client_parm.admin_addr)); |
---|
| 99 | client_parm.admin_addr.sin_family = hop->h_addrtype; |
---|
| 100 | memcpy((char *) &client_parm.admin_addr.sin_addr, (char *) hop->h_addr, |
---|
| 101 | hop->h_length); |
---|
| 102 | client_parm.admin_addr.sin_port = sep_port; |
---|
| 103 | |
---|
| 104 | return KADM_SUCCESS; |
---|
| 105 | } /* procedure kadm_init_link */ |
---|
| 106 | |
---|
| 107 | /* |
---|
| 108 | * kadm_change_pw |
---|
| 109 | * receives : key |
---|
| 110 | * |
---|
| 111 | * Replaces the password (i.e. des key) of the caller with that specified in |
---|
| 112 | * key. Returns no actual data from the master server, since this is called |
---|
| 113 | * by a user |
---|
| 114 | */ |
---|
[13755] | 115 | int |
---|
[11760] | 116 | kadm_change_pw(newkey) |
---|
| 117 | des_cblock newkey; /* The DES form of the users key */ |
---|
| 118 | { |
---|
| 119 | u_char *ret_st; |
---|
| 120 | int retval; |
---|
| 121 | |
---|
| 122 | retval = kadm_change_pw2(newkey, (char *)0, &ret_st); |
---|
| 123 | if (ret_st) |
---|
| 124 | free(ret_st); |
---|
| 125 | return(retval); |
---|
| 126 | } |
---|
| 127 | |
---|
| 128 | /* |
---|
| 129 | * kadm_change_pw2 |
---|
| 130 | * recieves : key, pw_string, ret_string |
---|
| 131 | * |
---|
| 132 | * Replaces the password (i.e. des key) of the caller with that specified in |
---|
| 133 | * key. Returns no actual data from the master server, since this is called |
---|
| 134 | * by a user |
---|
| 135 | */ |
---|
[13755] | 136 | int |
---|
[11760] | 137 | kadm_change_pw2(newkey, pwstring, retstring) |
---|
| 138 | des_cblock newkey; /* The DES form of the users key */ |
---|
| 139 | char *pwstring; |
---|
| 140 | u_char **retstring; |
---|
| 141 | { |
---|
| 142 | int stsize, retc; /* stream size and return code */ |
---|
| 143 | u_char *send_st; /* send stream */ |
---|
| 144 | u_char *ret_st; |
---|
| 145 | int ret_sz; |
---|
| 146 | unsigned KRB_INT32 keytmp; |
---|
| 147 | extern char *malloc(); |
---|
| 148 | |
---|
| 149 | *retstring = (u_char *) 0; |
---|
| 150 | |
---|
| 151 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 152 | return(retc); |
---|
| 153 | /* possible problem with vts_long on a non-multiple of four boundary */ |
---|
| 154 | |
---|
| 155 | stsize = 0; /* start of our output packet */ |
---|
| 156 | send_st = (u_char *) malloc(1);/* to make it reallocable */ |
---|
| 157 | send_st[stsize++] = (u_char) CHANGE_PW; |
---|
| 158 | |
---|
| 159 | /* change key to stream */ |
---|
| 160 | |
---|
| 161 | memcpy((char *) &keytmp, (char *) (((KRB_INT32 *) newkey) + 1), sizeof(KRB_INT32)); |
---|
| 162 | keytmp = htonl(keytmp); |
---|
| 163 | stsize += vts_long(keytmp, &send_st, stsize); |
---|
| 164 | |
---|
| 165 | memcpy((char *) &keytmp, (char *) newkey, sizeof(KRB_INT32)); |
---|
| 166 | keytmp = htonl(keytmp); |
---|
| 167 | stsize += vts_long(keytmp, &send_st, stsize); |
---|
| 168 | |
---|
| 169 | if (pwstring) { |
---|
| 170 | stsize += vts_string(pwstring, &send_st, stsize); |
---|
| 171 | } |
---|
| 172 | |
---|
| 173 | retc = kadm_cli_send(send_st, stsize, &ret_st, &ret_sz); |
---|
| 174 | free((char *)send_st); |
---|
| 175 | if (ret_sz) |
---|
| 176 | *retstring = ret_st; |
---|
| 177 | else { |
---|
| 178 | *retstring = 0; |
---|
| 179 | free(ret_st); |
---|
| 180 | } |
---|
| 181 | kadm_cli_disconn(); |
---|
| 182 | return(retc); |
---|
| 183 | } |
---|
| 184 | |
---|
| 185 | /* |
---|
| 186 | * kadm_add |
---|
| 187 | * receives : vals |
---|
| 188 | * returns : vals |
---|
| 189 | * |
---|
| 190 | * Adds an entry containing values to the database returns the values of the |
---|
| 191 | * entry, so if you leave certain fields blank you will be able to determine |
---|
| 192 | * the default values they are set to |
---|
| 193 | */ |
---|
| 194 | kadm_add(vals) |
---|
| 195 | Kadm_vals *vals; |
---|
| 196 | { |
---|
| 197 | u_char *st, *st2; /* st will hold the stream of values */ |
---|
| 198 | int st_len; /* st2 the final stream with opcode */ |
---|
| 199 | int retc; /* return code from call */ |
---|
| 200 | u_char *ret_st; |
---|
| 201 | int ret_sz; |
---|
| 202 | extern char *malloc(); |
---|
| 203 | |
---|
| 204 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 205 | return(retc); |
---|
| 206 | st_len = vals_to_stream(vals, &st); |
---|
| 207 | st2 = (u_char *) malloc((unsigned)(1 + st_len)); |
---|
| 208 | *st2 = (u_char) ADD_ENT; /* here's the opcode */ |
---|
| 209 | memcpy((char *) st2 + 1, (char *) st, st_len); /* append st on */ |
---|
| 210 | retc = kadm_cli_send(st2, st_len + 1, &ret_st, &ret_sz); |
---|
| 211 | free((char *)st); |
---|
| 212 | free((char *)st2); |
---|
| 213 | if (retc == KADM_SUCCESS) { |
---|
| 214 | /* ret_st has vals */ |
---|
| 215 | if (stream_to_vals(ret_st, vals, ret_sz) < 0) |
---|
| 216 | retc = KADM_LENGTH_ERROR; |
---|
| 217 | free((char *)ret_st); |
---|
| 218 | } |
---|
| 219 | kadm_cli_disconn(); |
---|
| 220 | return(retc); |
---|
| 221 | } |
---|
| 222 | |
---|
| 223 | /* |
---|
| 224 | * kadm_delete |
---|
| 225 | * receives : vals |
---|
| 226 | * returns : vals |
---|
| 227 | * |
---|
| 228 | * Deletes an entry containing values from the database. |
---|
| 229 | */ |
---|
| 230 | kadm_delete(vals) |
---|
| 231 | Kadm_vals *vals; |
---|
| 232 | { |
---|
| 233 | u_char *st, *st2; /* st will hold the stream of values */ |
---|
| 234 | int st_len; /* st2 the final stream with opcode */ |
---|
| 235 | int retc; /* return code from call */ |
---|
| 236 | u_char *ret_st; |
---|
| 237 | int ret_sz; |
---|
| 238 | extern char *malloc(); |
---|
| 239 | |
---|
| 240 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 241 | return(retc); |
---|
| 242 | st_len = vals_to_stream(vals, &st); |
---|
| 243 | st2 = (u_char *) malloc((unsigned)(1 + st_len)); |
---|
| 244 | *st2 = (u_char) DEL_ENT; /* here's the opcode */ |
---|
| 245 | memcpy((char *) st2 + 1, (char *) st, st_len); /* append st on */ |
---|
| 246 | retc = kadm_cli_send(st2, st_len + 1, &ret_st, &ret_sz); |
---|
| 247 | free((char *)st); |
---|
| 248 | free((char *)st2); |
---|
| 249 | if (retc == KADM_SUCCESS) { |
---|
| 250 | /* ret_st has vals */ |
---|
| 251 | if (stream_to_vals(ret_st, vals, ret_sz) < 0) |
---|
| 252 | retc = KADM_LENGTH_ERROR; |
---|
| 253 | free((char *)ret_st); |
---|
| 254 | } |
---|
| 255 | kadm_cli_disconn(); |
---|
| 256 | return(retc); |
---|
| 257 | } |
---|
| 258 | /* |
---|
| 259 | * kadm_mod |
---|
| 260 | * receives : KTEXT, {values, values} |
---|
| 261 | * returns : CKSUM, RETCODE, {values} |
---|
| 262 | * acl : su, sms (as register or dealloc) |
---|
| 263 | * |
---|
| 264 | * Modifies all entries corresponding to the first values so they match the |
---|
| 265 | * second values. returns the values for the changed entries in vals2 |
---|
| 266 | */ |
---|
| 267 | int kadm_mod(vals1, vals2) |
---|
| 268 | Kadm_vals *vals1; |
---|
| 269 | Kadm_vals *vals2; |
---|
| 270 | { |
---|
| 271 | u_char *st, *st2; /* st will hold the stream of values */ |
---|
| 272 | int st_len, nlen; /* st2 the final stream with opcode */ |
---|
| 273 | u_char *ret_st; |
---|
| 274 | int ret_sz; |
---|
| 275 | extern char *malloc(); |
---|
| 276 | extern char *realloc(); |
---|
| 277 | |
---|
| 278 | /* nlen is the length of second vals */ |
---|
| 279 | int retc; /* return code from call */ |
---|
| 280 | |
---|
| 281 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 282 | return(retc); |
---|
| 283 | |
---|
| 284 | st_len = vals_to_stream(vals1, &st); |
---|
| 285 | st2 = (u_char *) malloc((unsigned)(1 + st_len)); |
---|
| 286 | *st2 = (u_char) MOD_ENT; /* here's the opcode */ |
---|
| 287 | memcpy((char *) st2 + 1, (char *) st, st_len++); /* append st on */ |
---|
| 288 | free((char *)st); |
---|
| 289 | nlen = vals_to_stream(vals2, &st); |
---|
| 290 | st2 = (u_char *) realloc((char *) st2, (unsigned)(st_len + nlen)); |
---|
| 291 | memcpy((char *) st2 + st_len, (char *) st, nlen); /* append st on */ |
---|
| 292 | retc = kadm_cli_send(st2, st_len + nlen, &ret_st, &ret_sz); |
---|
| 293 | free((char *)st); |
---|
| 294 | free((char *)st2); |
---|
| 295 | if (retc == KADM_SUCCESS) { |
---|
| 296 | /* ret_st has vals */ |
---|
| 297 | if (stream_to_vals(ret_st, vals2, ret_sz) < 0) |
---|
| 298 | retc = KADM_LENGTH_ERROR; |
---|
| 299 | free((char *)ret_st); |
---|
| 300 | } |
---|
| 301 | kadm_cli_disconn(); |
---|
| 302 | return(retc); |
---|
| 303 | } |
---|
| 304 | |
---|
| 305 | /* |
---|
| 306 | * kadm_get |
---|
| 307 | * receives : KTEXT, {values, flags} |
---|
| 308 | * returns : CKSUM, RETCODE, {count, values, values, values} |
---|
| 309 | * acl : su |
---|
| 310 | * |
---|
| 311 | * gets the fields requested by flags from all entries matching values returns |
---|
| 312 | * this data for each matching recipient, after a count of how many such |
---|
| 313 | * matches there were |
---|
| 314 | */ |
---|
| 315 | int kadm_get(vals, fl) |
---|
| 316 | Kadm_vals *vals; |
---|
| 317 | u_char fl[4]; |
---|
| 318 | { |
---|
| 319 | int loop; /* for copying the fields data */ |
---|
| 320 | u_char *st, *st2; /* st will hold the stream of values */ |
---|
| 321 | int st_len; /* st2 the final stream with opcode */ |
---|
| 322 | int retc; /* return code from call */ |
---|
| 323 | u_char *ret_st; |
---|
| 324 | int ret_sz; |
---|
| 325 | extern char *malloc(); |
---|
| 326 | |
---|
| 327 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 328 | return(retc); |
---|
| 329 | st_len = vals_to_stream(vals, &st); |
---|
| 330 | st2 = (u_char *) malloc((unsigned)(1 + st_len + FLDSZ)); |
---|
| 331 | *st2 = (u_char) GET_ENT; /* here's the opcode */ |
---|
| 332 | memcpy((char *) st2 + 1, (char *) st, st_len); /* append st on */ |
---|
| 333 | for (loop = FLDSZ - 1; loop >= 0; loop--) |
---|
| 334 | *(st2 + st_len + FLDSZ - loop) = fl[loop]; /* append the flags */ |
---|
| 335 | retc = kadm_cli_send(st2, st_len + 1 + FLDSZ, &ret_st, &ret_sz); |
---|
| 336 | free((char *)st); |
---|
| 337 | free((char *)st2); |
---|
| 338 | if (retc == KADM_SUCCESS) { |
---|
| 339 | /* ret_st has vals */ |
---|
| 340 | if (stream_to_vals(ret_st, vals, ret_sz) < 0) |
---|
| 341 | retc = KADM_LENGTH_ERROR; |
---|
| 342 | free((char *)ret_st); |
---|
| 343 | } |
---|
| 344 | kadm_cli_disconn(); |
---|
| 345 | return(retc); |
---|
| 346 | } |
---|
| 347 | |
---|
| 348 | /* |
---|
| 349 | * kadm_check_pw |
---|
| 350 | * recieves : key, pw_string, ret_string |
---|
| 351 | * |
---|
| 352 | * Sends the password to the server and asks it if the password is a |
---|
| 353 | * "secure" password or not. Returns the error KADM_INSECURE_PW and |
---|
| 354 | * optionally returns a message if the password is not considered secure. |
---|
| 355 | */ |
---|
| 356 | int kadm_check_pw(newkey, pwstring, retstring) |
---|
| 357 | des_cblock newkey; /* The DES form of the users key */ |
---|
| 358 | char *pwstring; |
---|
| 359 | u_char **retstring; |
---|
| 360 | { |
---|
| 361 | int stsize, retc; /* stream size and return code */ |
---|
| 362 | u_char *send_st; /* send stream */ |
---|
| 363 | u_char *ret_st; |
---|
| 364 | int ret_sz; |
---|
| 365 | unsigned KRB_INT32 keytmp; |
---|
| 366 | extern char *malloc(); |
---|
| 367 | |
---|
| 368 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 369 | return(retc); |
---|
| 370 | /* possible problem with vts_long on a non-multiple of four boundary */ |
---|
| 371 | |
---|
| 372 | stsize = 0; /* start of our output packet */ |
---|
| 373 | send_st = (u_char *) malloc(1);/* to make it reallocable */ |
---|
| 374 | send_st[stsize++] = (u_char) CHECK_PW; |
---|
| 375 | |
---|
| 376 | /* change key to stream */ |
---|
| 377 | |
---|
| 378 | memcpy((char *) &keytmp, (char *) (((KRB_INT32 *) newkey) + 1), sizeof(KRB_INT32)); |
---|
| 379 | keytmp = htonl(keytmp); |
---|
| 380 | stsize += vts_long(keytmp, &send_st, stsize); |
---|
| 381 | |
---|
| 382 | memcpy((char *) &keytmp, (char *) newkey, sizeof(KRB_INT32)); |
---|
| 383 | keytmp = htonl(keytmp); |
---|
| 384 | stsize += vts_long(keytmp, &send_st, stsize); |
---|
| 385 | |
---|
| 386 | if (pwstring) { |
---|
| 387 | stsize += vts_string(pwstring, &send_st, stsize); |
---|
| 388 | } |
---|
| 389 | |
---|
| 390 | retc = kadm_cli_send(send_st, stsize, &ret_st, &ret_sz); |
---|
| 391 | free((char *)send_st); |
---|
| 392 | if (ret_sz) |
---|
| 393 | *retstring = ret_st; |
---|
| 394 | else { |
---|
| 395 | *retstring = 0; |
---|
| 396 | free(ret_st); |
---|
| 397 | } |
---|
| 398 | kadm_cli_disconn(); |
---|
| 399 | return(retc); |
---|
| 400 | } |
---|
| 401 | |
---|
| 402 | /* |
---|
| 403 | * kadm_change_srvtab |
---|
| 404 | * receives : name, instance |
---|
| 405 | * returns : values |
---|
| 406 | * |
---|
| 407 | * Asks the admin server to change the srvtab key for the specified |
---|
| 408 | * name, instance pair. The name, instance pair must be a valid |
---|
| 409 | * server principal. |
---|
| 410 | */ |
---|
| 411 | int kadm_change_srvtab(name, instance, values) |
---|
| 412 | char *name, *instance; |
---|
| 413 | Kadm_vals *values; |
---|
| 414 | { |
---|
| 415 | u_char *st, *st2; /* st will hold the stream of values */ |
---|
| 416 | int st_len; /* st2 the final stream with opcode */ |
---|
| 417 | int retc; /* return code from call */ |
---|
| 418 | u_char *ret_st; |
---|
| 419 | int ret_sz; |
---|
| 420 | Kadm_vals vals; |
---|
| 421 | extern char *malloc(); |
---|
| 422 | |
---|
| 423 | memset((char *) &vals, 0, sizeof(vals)); |
---|
| 424 | strncpy(vals.name, name, sizeof(vals.name)); |
---|
| 425 | strncpy(vals.instance, instance, sizeof(vals.instance)); |
---|
| 426 | SET_FIELD(KADM_NAME,vals.fields); |
---|
| 427 | SET_FIELD(KADM_INST,vals.fields); |
---|
| 428 | |
---|
| 429 | if ((retc = kadm_cli_conn()) != KADM_SUCCESS) |
---|
| 430 | return(retc); |
---|
| 431 | st_len = vals_to_stream(&vals, &st); |
---|
| 432 | st2 = (u_char *) malloc((unsigned)(1 + st_len)); |
---|
| 433 | *st2 = (u_char) CHG_STAB; /* here's the opcode */ |
---|
| 434 | memcpy((char *) st2 + 1, (char *) st, st_len); /* append st on */ |
---|
| 435 | retc = kadm_cli_send(st2, st_len + 1, &ret_st, &ret_sz); |
---|
| 436 | free((char *)st); |
---|
| 437 | free((char *)st2); |
---|
| 438 | if (retc == KADM_SUCCESS) { |
---|
| 439 | /* ret_st has vals */ |
---|
| 440 | if (stream_to_vals(ret_st, values, ret_sz) < 0) |
---|
| 441 | retc = KADM_LENGTH_ERROR; |
---|
| 442 | free((char *)ret_st); |
---|
| 443 | } |
---|
| 444 | kadm_cli_disconn(); |
---|
| 445 | return(retc); |
---|
| 446 | } |
---|
| 447 | |
---|
| 448 | /* |
---|
| 449 | * kadm_cli_send |
---|
| 450 | * recieves : opcode, packet, packet length, serv_name, serv_inst |
---|
| 451 | * returns : return code from the packet build, the server, or |
---|
| 452 | * something else |
---|
| 453 | * |
---|
| 454 | * It assembles a packet as follows: |
---|
| 455 | * 8 bytes : VERSION STRING |
---|
| 456 | * 4 bytes : LENGTH OF MESSAGE DATA and OPCODE |
---|
| 457 | * : KTEXT |
---|
| 458 | * : OPCODE \ |
---|
| 459 | * : DATA > Encrypted (with make priv) |
---|
| 460 | * : ...... / |
---|
| 461 | * |
---|
| 462 | * If it builds the packet and it is small enough, then it attempts to open the |
---|
| 463 | * connection to the admin server. If the connection is succesfully open |
---|
| 464 | * then it sends the data and waits for a reply. |
---|
| 465 | */ |
---|
| 466 | int kadm_cli_send(st_dat, st_siz, ret_dat, ret_siz) |
---|
| 467 | u_char *st_dat; /* the actual data */ |
---|
| 468 | int st_siz; /* length of said data */ |
---|
| 469 | u_char **ret_dat; /* to give return info */ |
---|
| 470 | int *ret_siz; /* length of returned info */ |
---|
| 471 | { |
---|
| 472 | int act_len; /* current offset into packet, return */ |
---|
| 473 | KRB_INT32 retdat; /* data */ |
---|
| 474 | KTEXT_ST authent; /* the authenticator we will build */ |
---|
| 475 | u_char *act_st; /* the pointer to the complete packet */ |
---|
| 476 | u_char *priv_pak; /* private version of the packet */ |
---|
| 477 | int priv_len; /* length of private packet */ |
---|
| 478 | u_long cksum; /* checksum of the packet */ |
---|
| 479 | MSG_DAT mdat; |
---|
| 480 | u_char *return_dat; |
---|
| 481 | extern char *malloc(); |
---|
| 482 | extern char *realloc(); |
---|
| 483 | |
---|
| 484 | act_st = (u_char *) malloc(KADM_VERSIZE); /* verstr stored first */ |
---|
| 485 | (void) strncpy((char *)act_st, KADM_VERSTR, KADM_VERSIZE); |
---|
| 486 | act_len = KADM_VERSIZE; |
---|
| 487 | |
---|
| 488 | if ((retdat = kadm_cli_keyd(sess_key, sess_sched)) != KADM_SUCCESS) { |
---|
| 489 | free((char *)act_st); |
---|
| 490 | return retdat; /* couldnt get key working */ |
---|
| 491 | } |
---|
| 492 | priv_pak = (u_char *) malloc((unsigned)(st_siz + 200)); |
---|
| 493 | /* 200 bytes for extra info case */ |
---|
| 494 | if ((priv_len = krb_mk_priv(st_dat, priv_pak, (u_long)st_siz, |
---|
| 495 | sess_sched, &sess_key, &client_parm.my_addr, |
---|
| 496 | &client_parm.admin_addr)) < 0) |
---|
| 497 | RET_N_FREE(KADM_NO_ENCRYPT); /* whoops... we got a lose |
---|
| 498 | * here */ |
---|
| 499 | /* here is the length of priv data. receiver calcs |
---|
| 500 | size of authenticator by subtracting vno size, priv size, and |
---|
| 501 | sizeof(u_long) (for the size indication) from total size */ |
---|
| 502 | |
---|
| 503 | act_len += vts_long((unsigned KRB_INT32) priv_len, &act_st, act_len); |
---|
| 504 | #ifdef NOENCRYPTION |
---|
| 505 | cksum = 0; |
---|
| 506 | #else |
---|
| 507 | cksum = quad_cksum(priv_pak, (unsigned KRB_INT32 *)0, (long)priv_len, |
---|
| 508 | 0, &sess_key); |
---|
| 509 | #endif |
---|
| 510 | if (retdat = krb_mk_req(&authent, client_parm.sname, client_parm.sinst, |
---|
| 511 | client_parm.krbrlm, (long)cksum)) { |
---|
| 512 | /* authenticator? */ |
---|
| 513 | RET_N_FREE(retdat + krb_err_base); |
---|
| 514 | } |
---|
| 515 | |
---|
| 516 | act_st = (u_char *) realloc((char *) act_st, |
---|
| 517 | (unsigned) (act_len + authent.length |
---|
| 518 | + priv_len)); |
---|
| 519 | if (!act_st) { |
---|
| 520 | clear_secrets(); |
---|
| 521 | free((char *)priv_pak); |
---|
| 522 | return(KADM_NOMEM); |
---|
| 523 | } |
---|
| 524 | memcpy((char *)act_st + act_len, (char *)authent.dat, authent.length); |
---|
| 525 | memcpy((char *)act_st + act_len + authent.length, (char *)priv_pak, |
---|
| 526 | priv_len); |
---|
| 527 | free((char *)priv_pak); |
---|
| 528 | if ((retdat = kadm_cli_out(act_st, |
---|
| 529 | act_len + authent.length + priv_len, |
---|
| 530 | ret_dat, ret_siz)) != KADM_SUCCESS) |
---|
| 531 | RET_N_FREE(retdat); |
---|
| 532 | free((char *)act_st); |
---|
| 533 | #define RET_N_FREE2(r) {free((char *)*ret_dat); *ret_dat = 0; *ret_siz = 0; clear_secrets(); return(r);} |
---|
| 534 | |
---|
| 535 | /* first see if it's a YOULOUSE */ |
---|
| 536 | if ((*ret_siz >= KADM_VERSIZE) && |
---|
| 537 | !strncmp(KADM_ULOSE, (char *)*ret_dat, KADM_VERSIZE)) |
---|
| 538 | { |
---|
| 539 | unsigned KRB_INT32 errcode; |
---|
| 540 | /* it's a youlose packet */ |
---|
| 541 | if (*ret_siz < KADM_VERSIZE + sizeof(unsigned KRB_INT32)) |
---|
| 542 | RET_N_FREE2(KADM_BAD_VER); |
---|
| 543 | memcpy((char *)&errcode, (char *)(*ret_dat) + KADM_VERSIZE, |
---|
| 544 | sizeof(unsigned KRB_INT32)); |
---|
| 545 | retdat = (int) ntohl(errcode); |
---|
| 546 | RET_N_FREE2(retdat); |
---|
| 547 | } |
---|
| 548 | /* need to decode the ret_dat */ |
---|
| 549 | if (retdat = krb_rd_priv(*ret_dat, (u_long)*ret_siz, sess_sched, |
---|
| 550 | &sess_key, &client_parm.admin_addr, |
---|
| 551 | &client_parm.my_addr, &mdat)) |
---|
| 552 | RET_N_FREE2(retdat+krb_err_base); |
---|
| 553 | if (mdat.app_length < KADM_VERSIZE + 4) |
---|
| 554 | /* too short! */ |
---|
| 555 | RET_N_FREE2(KADM_BAD_VER); |
---|
| 556 | if (strncmp((char *)mdat.app_data, KADM_VERSTR, KADM_VERSIZE)) |
---|
| 557 | /* bad version */ |
---|
| 558 | RET_N_FREE2(KADM_BAD_VER); |
---|
| 559 | memcpy((char *)&retdat, (char *)mdat.app_data+KADM_VERSIZE, |
---|
| 560 | sizeof(unsigned KRB_INT32)); |
---|
| 561 | retdat = ntohl((u_long)retdat); |
---|
| 562 | if ((mdat.app_length - KADM_VERSIZE - sizeof(unsigned KRB_INT32)) != 0) { |
---|
| 563 | if (!(return_dat = (u_char *) |
---|
| 564 | malloc((unsigned)(mdat.app_length - KADM_VERSIZE - |
---|
| 565 | sizeof(unsigned KRB_INT32))))) |
---|
| 566 | RET_N_FREE2(KADM_NOMEM); |
---|
| 567 | memcpy((char *)return_dat, |
---|
| 568 | (char *) mdat.app_data + KADM_VERSIZE + sizeof(unsigned KRB_INT32), |
---|
| 569 | (int)mdat.app_length - KADM_VERSIZE - sizeof(unsigned KRB_INT32)); |
---|
| 570 | } else { |
---|
| 571 | /* If it's zero length, still need to malloc a 1 byte string; */ |
---|
| 572 | /* malloc's of zero will return NULL on AIX & A/UX */ |
---|
| 573 | if (!(return_dat = (u_char *) malloc((unsigned) 1))) |
---|
| 574 | RET_N_FREE2(KADM_NOMEM); |
---|
| 575 | *return_dat = '\0'; |
---|
| 576 | } |
---|
| 577 | free((char *)*ret_dat); |
---|
| 578 | clear_secrets(); |
---|
| 579 | *ret_dat = return_dat; |
---|
| 580 | *ret_siz = mdat.app_length - KADM_VERSIZE - sizeof(unsigned KRB_INT32); |
---|
| 581 | return retdat; |
---|
| 582 | } |
---|
| 583 | |
---|
| 584 | /* takes in the sess_key and key_schedule and sets them appropriately */ |
---|
| 585 | int kadm_cli_keyd(s_k, s_s) |
---|
| 586 | des_cblock s_k; /* session key */ |
---|
| 587 | des_key_schedule s_s; /* session key schedule */ |
---|
| 588 | { |
---|
| 589 | CREDENTIALS cred; /* to get key data */ |
---|
| 590 | int stat; |
---|
| 591 | |
---|
| 592 | /* want .sname and .sinst here.... */ |
---|
| 593 | if (stat = krb_get_cred(client_parm.sname, client_parm.sinst, |
---|
| 594 | client_parm.krbrlm, &cred)) |
---|
| 595 | return stat + krb_err_base; |
---|
| 596 | memcpy((char *) s_k, (char *) cred.session, sizeof(des_cblock)); |
---|
| 597 | memset((char *) cred.session, 0, sizeof(des_cblock)); |
---|
| 598 | #ifdef NOENCRYPTION |
---|
| 599 | memset(s_s, 0, sizeof(des_key_schedule)); |
---|
| 600 | #else |
---|
| 601 | if (stat = key_sched(s_k, s_s)) |
---|
| 602 | return stat + krb_err_base; |
---|
| 603 | #endif |
---|
| 604 | return KADM_SUCCESS; |
---|
| 605 | } /* This code "works" */ |
---|
| 606 | |
---|
| 607 | /* Networking-specific routines have been moved out to kadm_net.c. */ |
---|