1/*
2 * Copyright (c) 1997 - 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the Institute nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "kadm5_locl.h"
35
36RCSID("$Id$");
37
38kadm5_ret_t
39kadm5_c_randkey_principal(void *server_handle,
40			  krb5_principal princ,
41			  krb5_boolean keepold,
42			  int n_ks_tuple,
43			  krb5_key_salt_tuple *ks_tuple,
44			  krb5_keyblock **new_keys,
45			  int *n_keys)
46{
47    kadm5_client_context *context = server_handle;
48    kadm5_ret_t ret;
49    krb5_storage *sp;
50    unsigned char buf[1536];
51    int32_t tmp;
52    size_t i;
53    krb5_data reply;
54
55    ret = _kadm5_connect(server_handle);
56    if(ret)
57	return ret;
58
59    sp = krb5_storage_from_mem(buf, sizeof(buf));
60    if (sp == NULL) {
61	krb5_clear_error_message(context->context);
62	return ENOMEM;
63    }
64
65    /*
66     * NOTE WELL: This message is extensible.  It currently consists of:
67     *
68     *  - opcode (kadm_randkey)
69     *  - principal name (princ)
70     *
71     * followed by optional items, each of which must be present if
72     * there are any items following them that are also present:
73     *
74     *  - keepold boolean (whether to delete old kvnos)
75     *  - number of key/salt type tuples
76     *  - array of {enctype, salttype}
77     *
78     * Eventually we may add:
79     *
80     *  - opaque string2key parameters (salt, rounds, ...)
81     */
82    krb5_store_int32(sp, kadm_randkey);
83    krb5_store_principal(sp, princ);
84
85    if (keepold == TRUE || n_ks_tuple > 0)
86	krb5_store_uint32(sp, keepold);
87    if (n_ks_tuple > 0)
88	krb5_store_uint32(sp, n_ks_tuple);
89    for (i = 0; i < (size_t)n_ks_tuple; i++) {
90	krb5_store_int32(sp, ks_tuple[i].ks_enctype);
91	krb5_store_int32(sp, ks_tuple[i].ks_salttype);
92    }
93    /* Future extensions go here */
94
95    ret = _kadm5_client_send(context, sp);
96    krb5_storage_free(sp);
97    if (ret)
98	return ret;
99    ret = _kadm5_client_recv(context, &reply);
100    if(ret)
101	return ret;
102    sp = krb5_storage_from_data(&reply);
103    if (sp == NULL) {
104	krb5_clear_error_message(context->context);
105	krb5_data_free (&reply);
106	return ENOMEM;
107    }
108    krb5_clear_error_message(context->context);
109    krb5_ret_int32(sp, &tmp);
110    ret = tmp;
111    if(ret == 0){
112	krb5_keyblock *k;
113
114	krb5_ret_int32(sp, &tmp);
115	if (tmp < 0) {
116	    ret = EOVERFLOW;
117	    goto out;
118	}
119	k = malloc(tmp * sizeof(*k));
120	if (k == NULL) {
121	    ret = ENOMEM;
122	    goto out;
123	}
124	for(i = 0; i < (size_t)tmp; i++)
125	    krb5_ret_keyblock(sp, &k[i]);
126	if (n_keys && new_keys) {
127	    *n_keys = tmp;
128	    *new_keys = k;
129	}
130    }
131out:
132    krb5_storage_free(sp);
133    krb5_data_free (&reply);
134    return ret;
135}
136