(nnpfs_lookup): adapt to netbsd-4 locking changes. From Pavel Cahyna
[arla.git] / rxgk / rxgk_crpc.c
blobd00f45da40e062ad27f331d16c649badb31714e8
1 /*
2 * Copyright (c) 2002 - 2004, Stockholms universitet
3 * (Stockholm University, 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 university 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND 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 COPYRIGHT OWNER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include "rxgk_locl.h"
36 RCSID("$Id$");
38 #include <rx/rx.h>
39 #include "rxgk_proto.h"
40 #include "rxgk_proto.cs.h"
42 static int
43 decrypt_clientinfo(RXGK_Token *opaque, struct RXGK_ClientInfo *ticket,
44 gss_ctx_id_t ctx)
46 size_t len;
47 const char *ret;
48 gss_buffer_desc encrypted_buffer;
49 gss_buffer_desc buffer;
50 OM_uint32 major_status, minor_status;
52 encrypted_buffer.value = opaque->val;
53 encrypted_buffer.length = opaque->len;
55 major_status = gss_unwrap(&minor_status,
56 ctx,
57 &encrypted_buffer,
58 &buffer,
59 NULL,
60 NULL);
61 if (GSS_ERROR(major_status)) {
62 _rxgk_gssapi_err(major_status, minor_status, GSS_C_NO_OID);
63 return EINVAL;
66 len = buffer.length;
67 ret = ydr_decode_RXGK_ClientInfo(ticket, buffer.value, &len);
69 major_status = gss_release_buffer(&minor_status, &buffer);
70 if (GSS_ERROR(major_status)) {
71 _rxgk_gssapi_err(major_status, minor_status, GSS_C_NO_OID);
72 free(opaque->val);
73 return EINVAL;
76 if (ret == NULL) {
77 return EINVAL;
80 return 0;
85 int
86 rxgk_get_gss_cred(uint32_t addr,
87 short port,
88 gss_name_t client_name,
89 gss_name_t target_name,
90 int32_t nametag,
91 int32_t *flags,
92 time_t *expire,
93 rxgk_level *minlevel,
94 RXGK_Ticket_Crypt *ticket,
95 struct rxgk_keyblock *key)
97 RXGK_Token opaque_in, opaque_out, rxgk_cred;
98 gss_buffer_desc input_token, output_token;
99 struct rx_securityClass *secobj;
100 struct rx_connection *conn;
101 RXGK_client_start client_start;
102 OM_uint32 minor_status, major_status;
103 uint32_t status;
104 gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
105 int ret, server_done = 0, client_done = 0;
106 int32_t enctypes[] = { RXGK_CRYPTO_AES256_CTS_HMAC_SHA1_96 };
107 char clientnonce[RXGK_MAX_NONCE];
109 memset(&client_start, 0, sizeof(client_start));
110 memset(key, 0, sizeof(*key));
111 memset(clientnonce, 0, sizeof(*clientnonce));
113 client_start.sp_enctypes.val = enctypes;
114 client_start.sp_enctypes.len = sizeof(enctypes)/sizeof(enctypes[0]);
115 client_start.sp_nametag = nametag;
116 client_start.sp_client_nonce.val = clientnonce;
117 client_start.sp_client_nonce.len = sizeof(clientnonce);
119 secobj = rxnull_NewClientSecurityObject();
121 conn = rx_NewConnection(addr, port, RXGK_SERVICE_ID, secobj, 0);
122 if (conn == NULL)
123 return ENETDOWN;
125 memset(&output_token, 0, sizeof(output_token));
126 memset(&input_token, 0, sizeof(input_token));
128 memset(&opaque_out, 0, sizeof(opaque_out));
129 memset(&opaque_in, 0, sizeof(opaque_in));
130 memset(&rxgk_cred, 0, sizeof(rxgk_cred));
133 * XXX unbreak statemachine
136 while (1) {
137 RXGK_Token input, output = { 0 , NULL };
139 opaque_in = opaque_out;
141 major_status = gss_init_sec_context(&minor_status,
142 GSS_C_NO_CREDENTIAL,
143 &ctx,
144 target_name,
145 GSS_C_NO_OID,
146 GSS_C_MUTUAL_FLAG|GSS_C_INTEG_FLAG,
147 GSS_C_INDEFINITE,
148 GSS_C_NO_CHANNEL_BINDINGS,
149 &input_token,
150 NULL,
151 &output_token,
152 NULL,
153 NULL);
154 if (output.len) {
155 free(output.val);
156 output.len = 0;
157 output.val = NULL;
159 if (major_status == GSS_S_COMPLETE && output_token.length == 0) {
160 ret = 0;
161 break;
162 } else if (major_status == GSS_S_COMPLETE) {
163 client_done = 1;
164 } else if (major_status != GSS_S_COMPLETE && server_done) {
165 _rxgk_gssapi_err(major_status, minor_status, GSS_C_NO_OID);
166 ret = EINVAL;
167 break;
168 } else if ((major_status & GSS_S_CONTINUE_NEEDED) == 0) {
169 _rxgk_gssapi_err(major_status, minor_status, GSS_C_NO_OID);
170 ret = EINVAL;
171 break;
174 input.val = output_token.value;
175 input.len = output_token.length;
177 ret = RXGK_GSSNegotiate(conn,
178 &client_start,
179 &input,
180 &opaque_in,
181 &output,
182 &opaque_out,
183 &status,
184 &rxgk_cred);
185 gss_release_buffer(&minor_status, &output_token);
186 if (opaque_in.len != 0) {
187 free(opaque_in.val);
188 opaque_in.len = 0;
190 if (ret) {
191 break;
194 if (status == GSS_S_COMPLETE && output.len == 0) {
195 ret = 0;
196 break;
197 } else if (client_done) {
198 ret = EINVAL;
199 break;
200 } else if (status == GSS_S_COMPLETE) {
201 server_done = 1;
202 } else if ((major_status & GSS_S_CONTINUE_NEEDED) == 0) {
203 ret = EINVAL;
204 break;
205 } else if (rxgk_cred.len) {
206 ret = EINVAL;
207 break;
209 input_token.value = output.val;
210 input_token.length = output.len;
213 rx_DestroyConnection(conn);
215 if (ret == 0) {
216 struct RXGK_ClientInfo clientinfo;
218 decrypt_clientinfo(&rxgk_cred, &clientinfo, ctx);
220 /* XXX select foo */
221 *flags = clientinfo.ci_flags;
222 *minlevel = clientinfo.ci_level;
224 ticket->val = clientinfo.ci_ticket.val;
225 ticket->len = clientinfo.ci_ticket.len;
227 ret = rxgk_derive_k0(ctx,
228 clientinfo.ci_server_nonce.val,
229 clientinfo.ci_server_nonce.len,
230 client_start.sp_client_nonce.val,
231 client_start.sp_client_nonce.len,
232 RXGK_CRYPTO_AES256_CTS_HMAC_SHA1_96,
233 key);
237 gss_delete_sec_context(&minor_status, &ctx, GSS_C_NO_BUFFER);
239 if (rxgk_cred.len)
240 free(rxgk_cred.val);
241 if (opaque_out.len != 0)
242 free(opaque_out.val);
244 return ret;