cf/largefile.m4: Fix build with autoconf-2.72
[heimdal.git] / lib / kadm5 / get_princs_c.c
blobbe86cfa579ef8e469c9ffd6691f09ba9c4089567
1 /*
2 * Copyright (c) 1997 - 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
34 #include "kadm5_locl.h"
36 RCSID("$Id$");
38 kadm5_ret_t
39 kadm5_c_get_principals(void *server_handle,
40 const char *expression,
41 char ***princs,
42 int *count)
44 kadm5_client_context *context = server_handle;
45 kadm5_ret_t ret;
46 krb5_storage *sp;
47 unsigned char buf[1024];
48 int32_t tmp;
49 krb5_data reply;
50 int i;
52 *count = 0;
53 *princs = NULL;
55 ret = _kadm5_connect(server_handle, 0 /* want_write */);
56 if (ret)
57 return ret;
59 krb5_data_zero(&reply);
61 sp = krb5_storage_from_mem(buf, sizeof(buf));
62 if (sp == NULL) {
63 ret = krb5_enomem(context->context);
64 goto out_keep_error;
66 ret = krb5_store_int32(sp, kadm_get_princs);
67 if (ret)
68 goto out;
69 ret = krb5_store_int32(sp, expression != NULL ? 1 : 0);
70 if (ret)
71 goto out;
72 if (expression) {
73 ret = krb5_store_string(sp, expression);
74 if (ret)
75 goto out;
77 ret = _kadm5_client_send(context, sp);
78 if (ret)
79 goto out_keep_error;
80 ret = _kadm5_client_recv(context, &reply);
81 if (ret)
82 goto out_keep_error;
83 krb5_storage_free(sp);
84 sp = krb5_storage_from_data (&reply);
85 if (sp == NULL) {
86 ret = krb5_enomem(context->context);
87 goto out_keep_error;
89 ret = krb5_ret_int32(sp, &tmp);
90 if (ret == 0)
91 ret = tmp;
93 if (ret)
94 goto out;
96 ret = krb5_ret_int32(sp, &tmp);
97 if (ret)
98 goto out;
100 *princs = calloc(tmp + 1, sizeof(**princs));
101 if (*princs == NULL) {
102 ret = krb5_enomem(context->context);
103 goto out_keep_error;
105 for (i = 0; i < tmp; i++) {
106 ret = krb5_ret_string(sp, &(*princs)[i]);
107 if (ret)
108 goto out;
110 *count = tmp;
112 out:
113 krb5_clear_error_message(context->context);
115 out_keep_error:
116 krb5_storage_free(sp);
117 krb5_data_free(&reply);
118 return ret;
121 kadm5_ret_t
122 kadm5_c_iter_principals(void *server_handle,
123 const char *expression,
124 int (*cb)(void *, const char *),
125 void *cbdata)
127 kadm5_client_context *context = server_handle;
128 kadm5_ret_t ret;
129 krb5_storage *sp;
130 unsigned char buf[1024];
131 int32_t tmp;
132 krb5_data reply;
133 size_t i;
134 int stop = 0;
136 ret = _kadm5_connect(server_handle, 0 /* want_write */);
137 if (ret)
138 return ret;
140 krb5_data_zero(&reply);
142 sp = krb5_storage_from_mem(buf, sizeof(buf));
143 if (sp == NULL) {
144 ret = krb5_enomem(context->context);
145 goto out_keep_error;
147 ret = krb5_store_int32(sp, kadm_get_princs);
148 if (ret)
149 goto out;
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);
161 if (ret)
162 goto out;
163 ret = krb5_store_string(sp, expression ? expression : "");
164 if (ret)
165 goto out;
166 ret = _kadm5_client_send(context, sp);
167 if (ret)
168 goto out_keep_error;
169 ret = _kadm5_client_recv(context, &reply);
170 if (ret)
171 goto out_keep_error;
172 krb5_storage_free(sp);
173 sp = krb5_storage_from_data (&reply);
174 if (sp == NULL) {
175 ret = krb5_enomem(context->context);
176 goto out_keep_error;
178 ret = krb5_ret_int32(sp, &tmp);
179 if (ret == 0)
180 ret = tmp;
182 if (ret)
183 goto out;
185 ret = krb5_ret_int32(sp, &tmp);
186 if (ret)
187 goto out;
189 if (tmp < 0) {
190 size_t n = -tmp;
191 int more = 1;
193 /* The server supports online iteration, hooray! */
195 while (more) {
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
201 * code.
203 krb5_data_free(&reply);
204 krb5_storage_free(sp);
205 sp = NULL;
206 ret = _kadm5_client_recv(context, &reply);
207 if (ret == 0 && (sp = krb5_storage_from_data(&reply)) == NULL)
208 ret = krb5_enomem(context->context);
209 if (ret)
210 goto out;
212 /* Every chunk begins with a status code */
213 ret = krb5_ret_int32(sp, &tmp);
214 if (ret == 0)
215 ret = tmp;
216 if (ret)
217 goto out;
219 /* We expect up to -tmp principals per reply */
220 for (i = 0; i < n; i++) {
221 char *princ = NULL;
223 ret = krb5_ret_string(sp, &princ);
224 if (ret == HEIM_ERR_EOF) {
225 /* This was the last reply */
226 more = 0;
227 ret = 0;
228 break;
230 if (ret)
231 goto out;
232 if (!stop) {
233 stop = cb(cbdata, princ);
234 if (stop) {
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
241 * finished.
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);
250 free(princ);
253 /* Get the final result code */
254 krb5_data_free(&reply);
255 krb5_storage_free(sp);
256 sp = NULL;
257 ret = _kadm5_client_recv(context, &reply);
258 if (ret == 0 && (sp = krb5_storage_from_data(&reply)) == NULL)
259 ret = krb5_enomem(context->context);
260 if (ret)
261 goto out;
262 ret = krb5_ret_int32(sp, &tmp);
263 if (ret == 0)
264 ret = tmp;
265 if (!stop) {
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);
275 } else {
276 size_t n = tmp;
278 /* Old server -- listing not online */
279 for (i = 0; i < n; i++) {
280 char *princ = NULL;
282 ret = krb5_ret_string(sp, &princ);
283 if (ret)
284 goto out;
285 cb(cbdata, princ);
286 free(princ);
290 out:
291 krb5_clear_error_message(context->context);
293 out_keep_error:
294 if (stop)
295 ret = stop;
296 krb5_storage_free(sp);
297 krb5_data_free(&reply);
298 return ret;