Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / libafscp / afscp_util.c
blobac74252ad2859dd7ff698d3e9e7a466c51a312df
1 /* AUTORIGHTS
2 Copyright (C) 2003 - 2010 Chaskiel Grundman
3 All rights reserved
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
16 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include <afsconfig.h>
28 #include <afs/param.h>
30 #include <ctype.h>
31 #include <afs/cellconfig.h>
32 #ifndef AFSCONF_CLIENTNAME
33 #include <afs/dirpath.h>
34 #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
35 #endif
36 #include <ubik.h>
37 #include <rx/rx_null.h>
38 #include <rx/rxkad.h>
39 #ifdef HAVE_KERBEROS
40 # define KERBEROS_APPLE_DEPRECATED(x)
41 # include <krb5.h>
42 #endif
43 #include "afscp.h"
44 #include "afscp_internal.h"
46 #ifdef HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
47 #define Z_keydata(keyblock) ((keyblock)->contents)
48 #define Z_keylen(keyblock) ((keyblock)->length)
49 #define Z_credskey(creds) (&(creds)->keyblock)
50 #define Z_enctype(keyblock) ((keyblock)->enctype)
51 #else
52 #define Z_keydata(keyblock) ((keyblock)->keyvalue.data)
53 #define Z_keylen(keyblock) ((keyblock)->keyvalue.length)
54 #define Z_credskey(creds) (&(creds)->session)
55 #define Z_enctype(keyblock) ((keyblock)->keytype)
56 #endif
58 static int insecure = 0;
59 static int try_anonymous = 0;
61 int
62 afscp_Insecure(void)
64 insecure = 1;
65 return 0;
68 int
69 afscp_AnonymousAuth(int state)
71 try_anonymous = state;
72 return 0;
75 static struct afsconf_dir *confdir;
77 void
78 afscp_SetConfDir(char *confDir)
80 if (confdir != NULL)
81 afsconf_Close(confdir);
83 confdir = afsconf_Open(confDir);
86 static int
87 _GetCellInfo(char *cell, struct afsconf_cell *celldata)
89 int code;
90 if (confdir == NULL)
91 confdir = afsconf_Open(AFSCONF_CLIENTNAME);
92 if (confdir == NULL) {
93 return AFSCONF_NODB;
95 code = afsconf_GetCellInfo(confdir, cell, AFSCONF_VLDBSERVICE, celldata);
96 return code;
99 static int
100 _GetNullSecurityObject(struct afscp_cell *cell)
102 cell->security = (struct rx_securityClass *)rxnull_NewClientSecurityObject();
103 cell->scindex = RX_SECIDX_NULL;
104 return 0;
108 _GetSecurityObject(struct afscp_cell *cell)
110 int code = ENOENT;
111 #ifdef HAVE_KERBEROS
112 krb5_context context;
113 krb5_creds match;
114 krb5_creds *cred;
115 krb5_ccache cc;
116 char **realms, *realm;
117 struct afsconf_cell celldata;
118 char localcell[MAXCELLCHARS + 1];
119 struct rx_securityClass *sc;
120 struct ktc_encryptionKey k;
121 int i;
122 rxkad_level l;
123 code = _GetCellInfo(cell->name, &celldata);
124 if (code != 0) {
125 goto try_anon;
128 code = krb5_init_context(&context); /* see aklog.c main() */
129 if (code != 0) {
130 goto try_anon;
133 if (cell->realm == NULL) {
134 realm = NULL;
135 code = krb5_get_host_realm(context, celldata.hostName[0], &realms);
137 if (code == 0) {
138 strlcpy(localcell, realms[0], sizeof(localcell));
139 krb5_free_host_realm(context, realms);
140 realm = localcell;
142 } else {
143 realm = cell->realm;
144 strlcpy(localcell, realm, MAXCELLCHARS + 1);
146 if (realm)
147 if (realm == NULL) {
148 for (i = 0; (i < MAXCELLCHARS && cell->name[i]); i++) {
149 if (isalpha(cell->name[i]))
150 localcell[i] = toupper(cell->name[i]);
151 else
152 localcell[i] = cell->name[i];
154 localcell[i] = '\0';
155 realm = localcell;
157 cc = NULL;
158 code = krb5_cc_default(context, &cc);
160 memset(&match, 0, sizeof(match));
161 Z_enctype(Z_credskey(&match)) = ENCTYPE_DES_CBC_CRC;
163 if (code == 0)
164 code = krb5_cc_get_principal(context, cc, &match.client);
165 if (code == 0)
166 code = krb5_build_principal(context, &match.server,
167 strlen(realm), realm,
168 "afs", cell->name, NULL);
170 if (code != 0) {
171 krb5_free_cred_contents(context, &match);
172 if (cc)
173 krb5_cc_close(context, cc);
174 krb5_free_context(context);
175 goto try_anon;
178 code = krb5_get_credentials(context, 0, cc, &match, &cred);
179 if (code != 0) {
180 krb5_free_principal(context, match.server);
181 match.server = NULL;
183 code = krb5_build_principal(context, &match.server,
184 strlen(realm), realm, "afs", (void *)NULL);
185 if (code == 0)
186 code = krb5_get_credentials(context, 0, cc, &match, &cred);
187 if (code != 0) {
188 krb5_free_cred_contents(context, &match);
189 if (cc)
190 krb5_cc_close(context, cc);
191 krb5_free_context(context);
192 goto try_anon;
196 if (insecure)
197 l = rxkad_clear;
198 else
199 l = rxkad_crypt;
200 memcpy(&k.data, Z_keydata(Z_credskey(cred)), 8);
201 sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject
202 (l, &k, RXKAD_TKT_TYPE_KERBEROS_V5,
203 cred->ticket.length, cred->ticket.data);
204 krb5_free_creds(context, cred);
205 krb5_free_cred_contents(context, &match);
206 if (cc)
207 krb5_cc_close(context, cc);
208 krb5_free_context(context);
209 cell->security = sc;
210 cell->scindex = 2;
211 return 0;
213 try_anon:
214 #endif /* HAVE_KERBEROS */
215 if (try_anonymous)
216 return _GetNullSecurityObject(cell);
217 else
218 return code;
222 _GetVLservers(struct afscp_cell *cell)
224 struct rx_connection *conns[MAXHOSTSPERCELL + 1];
225 int i;
226 int code;
227 struct afsconf_cell celldata;
229 code = _GetCellInfo(cell->name, &celldata);
230 if (code != 0) {
231 return code;
234 for (i = 0; i < celldata.numServers; i++) {
235 conns[i] = rx_NewConnection(celldata.hostAddr[i].sin_addr.s_addr,
236 htons(AFSCONF_VLDBPORT),
237 USER_SERVICE_ID, cell->security,
238 cell->scindex);
240 conns[i] = 0;
241 return ubik_ClientInit(conns, &cell->vlservers);