2 * Copyright (c) 1997 - 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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
34 #include "kadm5_locl.h"
39 kadm5_c_get_principals(void *server_handle
,
40 const char *expression
,
44 kadm5_client_context
*context
= server_handle
;
47 unsigned char buf
[1024];
55 ret
= _kadm5_connect(server_handle
, 0 /* want_write */);
59 krb5_data_zero(&reply
);
61 sp
= krb5_storage_from_mem(buf
, sizeof(buf
));
63 ret
= krb5_enomem(context
->context
);
66 ret
= krb5_store_int32(sp
, kadm_get_princs
);
69 ret
= krb5_store_int32(sp
, expression
!= NULL
? 1 : 0);
73 ret
= krb5_store_string(sp
, expression
);
77 ret
= _kadm5_client_send(context
, sp
);
80 ret
= _kadm5_client_recv(context
, &reply
);
83 krb5_storage_free(sp
);
84 sp
= krb5_storage_from_data (&reply
);
86 ret
= krb5_enomem(context
->context
);
89 ret
= krb5_ret_int32(sp
, &tmp
);
96 ret
= krb5_ret_int32(sp
, &tmp
);
100 *princs
= calloc(tmp
+ 1, sizeof(**princs
));
101 if (*princs
== NULL
) {
102 ret
= krb5_enomem(context
->context
);
105 for (i
= 0; i
< tmp
; i
++) {
106 ret
= krb5_ret_string(sp
, &(*princs
)[i
]);
113 krb5_clear_error_message(context
->context
);
116 krb5_storage_free(sp
);
117 krb5_data_free(&reply
);
122 kadm5_c_iter_principals(void *server_handle
,
123 const char *expression
,
124 int (*cb
)(void *, const char *),
127 kadm5_client_context
*context
= server_handle
;
130 unsigned char buf
[1024];
136 ret
= _kadm5_connect(server_handle
, 0 /* want_write */);
140 krb5_data_zero(&reply
);
142 sp
= krb5_storage_from_mem(buf
, sizeof(buf
));
144 ret
= krb5_enomem(context
->context
);
147 ret
= krb5_store_int32(sp
, kadm_get_princs
);
152 * Our protocol has an int boolean for this operation to indicate whether
153 * there's an expression. What we'll do here is that instead of sending
154 * just false or trueish, for online iteration we'll send a number other
155 * than 0 or 1 -- a magic value > 0 and < INT_MAX.
157 * In response we'll expect multiple replies, each with up to some small
158 * number of principal names. See kadmin/server.c.
160 ret
= krb5_store_int32(sp
, 0x55555555);
163 ret
= krb5_store_string(sp
, expression
? expression
: "");
166 ret
= _kadm5_client_send(context
, sp
);
169 ret
= _kadm5_client_recv(context
, &reply
);
172 krb5_storage_free(sp
);
173 sp
= krb5_storage_from_data (&reply
);
175 ret
= krb5_enomem(context
->context
);
178 ret
= krb5_ret_int32(sp
, &tmp
);
185 ret
= krb5_ret_int32(sp
, &tmp
);
193 /* The server supports online iteration, hooray! */
197 * We expect any number of chunks, each having `n' names, except
198 * the last one would have fewer than `n' (possibly zero, even).
200 * After that we expect one more reply with just a final return
203 krb5_data_free(&reply
);
204 krb5_storage_free(sp
);
206 ret
= _kadm5_client_recv(context
, &reply
);
207 if (ret
== 0 && (sp
= krb5_storage_from_data(&reply
)) == NULL
)
208 ret
= krb5_enomem(context
->context
);
212 /* Every chunk begins with a status code */
213 ret
= krb5_ret_int32(sp
, &tmp
);
219 /* We expect up to -tmp principals per reply */
220 for (i
= 0; i
< n
; i
++) {
223 ret
= krb5_ret_string(sp
, &princ
);
224 if (ret
== HEIM_ERR_EOF
) {
225 /* This was the last reply */
233 stop
= cb(cbdata
, princ
);
236 * Tell the server to stop.
238 * We use a NOP for this, but with a payload that says
239 * "don't reply to the NOP" just in case the NOP
240 * arrives and is processed _after_ the LISTing has
243 krb5_storage_free(sp
);
244 if ((sp
= krb5_storage_emem()) &&
245 krb5_store_int32(sp
, kadm_nop
) == 0 &&
246 krb5_store_int32(sp
, 0))
247 (void) _kadm5_client_send(context
, sp
);
253 /* Get the final result code */
254 krb5_data_free(&reply
);
255 krb5_storage_free(sp
);
257 ret
= _kadm5_client_recv(context
, &reply
);
258 if (ret
== 0 && (sp
= krb5_storage_from_data(&reply
)) == NULL
)
259 ret
= krb5_enomem(context
->context
);
262 ret
= krb5_ret_int32(sp
, &tmp
);
267 * Send our "interrupt" after the last chunk if we hand't
268 * interrupted already.
270 krb5_storage_free(sp
);
271 if ((sp
= krb5_storage_emem()) &&
272 krb5_store_int32(sp
, kadm_nop
) == 0)
273 (void) _kadm5_client_send(context
, sp
);
278 /* Old server -- listing not online */
279 for (i
= 0; i
< n
; i
++) {
282 ret
= krb5_ret_string(sp
, &princ
);
291 krb5_clear_error_message(context
->context
);
296 krb5_storage_free(sp
);
297 krb5_data_free(&reply
);