xref: /freebsd/crypto/heimdal/lib/krb5/scache.c (revision ae771770)
1*ae771770SStanislav Sedov /*
2*ae771770SStanislav Sedov  * Copyright (c) 2008 Kungliga Tekniska Högskolan
3*ae771770SStanislav Sedov  * (Royal Institute of Technology, Stockholm, Sweden).
4*ae771770SStanislav Sedov  * All rights reserved.
5*ae771770SStanislav Sedov  *
6*ae771770SStanislav Sedov  * Redistribution and use in source and binary forms, with or without
7*ae771770SStanislav Sedov  * modification, are permitted provided that the following conditions
8*ae771770SStanislav Sedov  * are met:
9*ae771770SStanislav Sedov  *
10*ae771770SStanislav Sedov  * 1. Redistributions of source code must retain the above copyright
11*ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer.
12*ae771770SStanislav Sedov  *
13*ae771770SStanislav Sedov  * 2. Redistributions in binary form must reproduce the above copyright
14*ae771770SStanislav Sedov  *    notice, this list of conditions and the following disclaimer in the
15*ae771770SStanislav Sedov  *    documentation and/or other materials provided with the distribution.
16*ae771770SStanislav Sedov  *
17*ae771770SStanislav Sedov  * 3. Neither the name of the Institute nor the names of its contributors
18*ae771770SStanislav Sedov  *    may be used to endorse or promote products derived from this software
19*ae771770SStanislav Sedov  *    without specific prior written permission.
20*ae771770SStanislav Sedov  *
21*ae771770SStanislav Sedov  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22*ae771770SStanislav Sedov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23*ae771770SStanislav Sedov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24*ae771770SStanislav Sedov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25*ae771770SStanislav Sedov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26*ae771770SStanislav Sedov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27*ae771770SStanislav Sedov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28*ae771770SStanislav Sedov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29*ae771770SStanislav Sedov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30*ae771770SStanislav Sedov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*ae771770SStanislav Sedov  * SUCH DAMAGE.
32*ae771770SStanislav Sedov  */
33*ae771770SStanislav Sedov 
34*ae771770SStanislav Sedov #include "krb5_locl.h"
35*ae771770SStanislav Sedov 
36*ae771770SStanislav Sedov #ifdef HAVE_SCC
37*ae771770SStanislav Sedov 
38*ae771770SStanislav Sedov #include <sqlite3.h>
39*ae771770SStanislav Sedov 
40*ae771770SStanislav Sedov typedef struct krb5_scache {
41*ae771770SStanislav Sedov     char *name;
42*ae771770SStanislav Sedov     char *file;
43*ae771770SStanislav Sedov     sqlite3 *db;
44*ae771770SStanislav Sedov 
45*ae771770SStanislav Sedov     sqlite_uint64 cid;
46*ae771770SStanislav Sedov 
47*ae771770SStanislav Sedov     sqlite3_stmt *icred;
48*ae771770SStanislav Sedov     sqlite3_stmt *dcred;
49*ae771770SStanislav Sedov     sqlite3_stmt *iprincipal;
50*ae771770SStanislav Sedov 
51*ae771770SStanislav Sedov     sqlite3_stmt *icache;
52*ae771770SStanislav Sedov     sqlite3_stmt *ucachen;
53*ae771770SStanislav Sedov     sqlite3_stmt *ucachep;
54*ae771770SStanislav Sedov     sqlite3_stmt *dcache;
55*ae771770SStanislav Sedov     sqlite3_stmt *scache;
56*ae771770SStanislav Sedov     sqlite3_stmt *scache_name;
57*ae771770SStanislav Sedov     sqlite3_stmt *umaster;
58*ae771770SStanislav Sedov 
59*ae771770SStanislav Sedov } krb5_scache;
60*ae771770SStanislav Sedov 
61*ae771770SStanislav Sedov #define	SCACHE(X)	((krb5_scache *)(X)->data.data)
62*ae771770SStanislav Sedov 
63*ae771770SStanislav Sedov #define SCACHE_DEF_NAME		"Default-cache"
64*ae771770SStanislav Sedov #ifdef KRB5_USE_PATH_TOKENS
65*ae771770SStanislav Sedov #define KRB5_SCACHE_DB	"%{TEMP}/krb5scc_%{uid}"
66*ae771770SStanislav Sedov #else
67*ae771770SStanislav Sedov #define KRB5_SCACHE_DB	"/tmp/krb5scc_%{uid}"
68*ae771770SStanislav Sedov #endif
69*ae771770SStanislav Sedov #define KRB5_SCACHE_NAME	"SCC:"  SCACHE_DEF_NAME ":" KRB5_SCACHE_DB
70*ae771770SStanislav Sedov 
71*ae771770SStanislav Sedov #define SCACHE_INVALID_CID	((sqlite_uint64)-1)
72*ae771770SStanislav Sedov 
73*ae771770SStanislav Sedov /*
74*ae771770SStanislav Sedov  *
75*ae771770SStanislav Sedov  */
76*ae771770SStanislav Sedov 
77*ae771770SStanislav Sedov #define SQL_CMASTER ""				\
78*ae771770SStanislav Sedov 	"CREATE TABLE master ("			\
79*ae771770SStanislav Sedov         "oid INTEGER PRIMARY KEY,"		\
80*ae771770SStanislav Sedov 	"version INTEGER NOT NULL,"		\
81*ae771770SStanislav Sedov 	"defaultcache TEXT NOT NULL"		\
82*ae771770SStanislav Sedov 	")"
83*ae771770SStanislav Sedov 
84*ae771770SStanislav Sedov #define SQL_SETUP_MASTER \
85*ae771770SStanislav Sedov 	"INSERT INTO master (version,defaultcache) VALUES(2, \"" SCACHE_DEF_NAME "\")"
86*ae771770SStanislav Sedov #define SQL_UMASTER "UPDATE master SET defaultcache=? WHERE version=2"
87*ae771770SStanislav Sedov 
88*ae771770SStanislav Sedov #define SQL_CCACHE ""				\
89*ae771770SStanislav Sedov 	"CREATE TABLE caches ("			\
90*ae771770SStanislav Sedov         "oid INTEGER PRIMARY KEY,"		\
91*ae771770SStanislav Sedov 	"principal TEXT,"			\
92*ae771770SStanislav Sedov 	"name TEXT NOT NULL"			\
93*ae771770SStanislav Sedov 	")"
94*ae771770SStanislav Sedov 
95*ae771770SStanislav Sedov #define SQL_TCACHE ""						\
96*ae771770SStanislav Sedov 	"CREATE TRIGGER CacheDropCreds AFTER DELETE ON caches "	\
97*ae771770SStanislav Sedov 	"FOR EACH ROW BEGIN "					\
98*ae771770SStanislav Sedov 	"DELETE FROM credentials WHERE cid=old.oid;"		\
99*ae771770SStanislav Sedov 	"END"
100*ae771770SStanislav Sedov 
101*ae771770SStanislav Sedov #define SQL_ICACHE "INSERT INTO caches (name) VALUES(?)"
102*ae771770SStanislav Sedov #define SQL_UCACHE_NAME "UPDATE caches SET name=? WHERE OID=?"
103*ae771770SStanislav Sedov #define SQL_UCACHE_PRINCIPAL "UPDATE caches SET principal=? WHERE OID=?"
104*ae771770SStanislav Sedov #define SQL_DCACHE "DELETE FROM caches WHERE OID=?"
105*ae771770SStanislav Sedov #define SQL_SCACHE "SELECT principal,name FROM caches WHERE OID=?"
106*ae771770SStanislav Sedov #define SQL_SCACHE_NAME "SELECT oid FROM caches WHERE NAME=?"
107*ae771770SStanislav Sedov 
108*ae771770SStanislav Sedov #define SQL_CCREDS ""				\
109*ae771770SStanislav Sedov 	"CREATE TABLE credentials ("		\
110*ae771770SStanislav Sedov         "oid INTEGER PRIMARY KEY,"		\
111*ae771770SStanislav Sedov 	"cid INTEGER NOT NULL,"			\
112*ae771770SStanislav Sedov 	"kvno INTEGER NOT NULL,"		\
113*ae771770SStanislav Sedov 	"etype INTEGER NOT NULL,"		\
114*ae771770SStanislav Sedov         "created_at INTEGER NOT NULL,"		\
115*ae771770SStanislav Sedov 	"cred BLOB NOT NULL"			\
116*ae771770SStanislav Sedov 	")"
117*ae771770SStanislav Sedov 
118*ae771770SStanislav Sedov #define SQL_TCRED ""							\
119*ae771770SStanislav Sedov 	"CREATE TRIGGER credDropPrincipal AFTER DELETE ON credentials "	\
120*ae771770SStanislav Sedov 	"FOR EACH ROW BEGIN "						\
121*ae771770SStanislav Sedov 	"DELETE FROM principals WHERE credential_id=old.oid;"		\
122*ae771770SStanislav Sedov 	"END"
123*ae771770SStanislav Sedov 
124*ae771770SStanislav Sedov #define SQL_ICRED "INSERT INTO credentials (cid, kvno, etype, cred, created_at) VALUES (?,?,?,?,?)"
125*ae771770SStanislav Sedov #define SQL_DCRED "DELETE FROM credentials WHERE cid=?"
126*ae771770SStanislav Sedov 
127*ae771770SStanislav Sedov #define SQL_CPRINCIPALS ""			\
128*ae771770SStanislav Sedov 	"CREATE TABLE principals ("		\
129*ae771770SStanislav Sedov         "oid INTEGER PRIMARY KEY,"		\
130*ae771770SStanislav Sedov 	"principal TEXT NOT NULL,"		\
131*ae771770SStanislav Sedov 	"type INTEGER NOT NULL,"		\
132*ae771770SStanislav Sedov 	"credential_id INTEGER NOT NULL"	\
133*ae771770SStanislav Sedov 	")"
134*ae771770SStanislav Sedov 
135*ae771770SStanislav Sedov #define SQL_IPRINCIPAL "INSERT INTO principals (principal, type, credential_id) VALUES (?,?,?)"
136*ae771770SStanislav Sedov 
137*ae771770SStanislav Sedov /*
138*ae771770SStanislav Sedov  * sqlite destructors
139*ae771770SStanislav Sedov  */
140*ae771770SStanislav Sedov 
141*ae771770SStanislav Sedov static void
free_data(void * data)142*ae771770SStanislav Sedov free_data(void *data)
143*ae771770SStanislav Sedov {
144*ae771770SStanislav Sedov     free(data);
145*ae771770SStanislav Sedov }
146*ae771770SStanislav Sedov 
147*ae771770SStanislav Sedov static void
free_krb5(void * str)148*ae771770SStanislav Sedov free_krb5(void *str)
149*ae771770SStanislav Sedov {
150*ae771770SStanislav Sedov     krb5_xfree(str);
151*ae771770SStanislav Sedov }
152*ae771770SStanislav Sedov 
153*ae771770SStanislav Sedov static void
scc_free(krb5_scache * s)154*ae771770SStanislav Sedov scc_free(krb5_scache *s)
155*ae771770SStanislav Sedov {
156*ae771770SStanislav Sedov     if (s->file)
157*ae771770SStanislav Sedov 	free(s->file);
158*ae771770SStanislav Sedov     if (s->name)
159*ae771770SStanislav Sedov 	free(s->name);
160*ae771770SStanislav Sedov 
161*ae771770SStanislav Sedov     if (s->icred)
162*ae771770SStanislav Sedov 	sqlite3_finalize(s->icred);
163*ae771770SStanislav Sedov     if (s->dcred)
164*ae771770SStanislav Sedov 	sqlite3_finalize(s->dcred);
165*ae771770SStanislav Sedov     if (s->iprincipal)
166*ae771770SStanislav Sedov 	sqlite3_finalize(s->iprincipal);
167*ae771770SStanislav Sedov     if (s->icache)
168*ae771770SStanislav Sedov 	sqlite3_finalize(s->icache);
169*ae771770SStanislav Sedov     if (s->ucachen)
170*ae771770SStanislav Sedov 	sqlite3_finalize(s->ucachen);
171*ae771770SStanislav Sedov     if (s->ucachep)
172*ae771770SStanislav Sedov 	sqlite3_finalize(s->ucachep);
173*ae771770SStanislav Sedov     if (s->dcache)
174*ae771770SStanislav Sedov 	sqlite3_finalize(s->dcache);
175*ae771770SStanislav Sedov     if (s->scache)
176*ae771770SStanislav Sedov 	sqlite3_finalize(s->scache);
177*ae771770SStanislav Sedov     if (s->scache_name)
178*ae771770SStanislav Sedov 	sqlite3_finalize(s->scache_name);
179*ae771770SStanislav Sedov     if (s->umaster)
180*ae771770SStanislav Sedov 	sqlite3_finalize(s->umaster);
181*ae771770SStanislav Sedov 
182*ae771770SStanislav Sedov     if (s->db)
183*ae771770SStanislav Sedov 	sqlite3_close(s->db);
184*ae771770SStanislav Sedov     free(s);
185*ae771770SStanislav Sedov }
186*ae771770SStanislav Sedov 
187*ae771770SStanislav Sedov #ifdef TRACEME
188*ae771770SStanislav Sedov static void
trace(void * ptr,const char * str)189*ae771770SStanislav Sedov trace(void* ptr, const char * str)
190*ae771770SStanislav Sedov {
191*ae771770SStanislav Sedov     printf("SQL: %s\n", str);
192*ae771770SStanislav Sedov }
193*ae771770SStanislav Sedov #endif
194*ae771770SStanislav Sedov 
195*ae771770SStanislav Sedov static krb5_error_code
prepare_stmt(krb5_context context,sqlite3 * db,sqlite3_stmt ** stmt,const char * str)196*ae771770SStanislav Sedov prepare_stmt(krb5_context context, sqlite3 *db,
197*ae771770SStanislav Sedov 	     sqlite3_stmt **stmt, const char *str)
198*ae771770SStanislav Sedov {
199*ae771770SStanislav Sedov     int ret;
200*ae771770SStanislav Sedov 
201*ae771770SStanislav Sedov     ret = sqlite3_prepare_v2(db, str, -1, stmt, NULL);
202*ae771770SStanislav Sedov     if (ret != SQLITE_OK) {
203*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOENT,
204*ae771770SStanislav Sedov 			       N_("Failed to prepare stmt %s: %s", ""),
205*ae771770SStanislav Sedov 			       str, sqlite3_errmsg(db));
206*ae771770SStanislav Sedov 	return ENOENT;
207*ae771770SStanislav Sedov     }
208*ae771770SStanislav Sedov     return 0;
209*ae771770SStanislav Sedov }
210*ae771770SStanislav Sedov 
211*ae771770SStanislav Sedov static krb5_error_code
exec_stmt(krb5_context context,sqlite3 * db,const char * str,krb5_error_code code)212*ae771770SStanislav Sedov exec_stmt(krb5_context context, sqlite3 *db, const char *str,
213*ae771770SStanislav Sedov 	  krb5_error_code code)
214*ae771770SStanislav Sedov {
215*ae771770SStanislav Sedov     int ret;
216*ae771770SStanislav Sedov 
217*ae771770SStanislav Sedov     ret = sqlite3_exec(db, str, NULL, NULL, NULL);
218*ae771770SStanislav Sedov     if (ret != SQLITE_OK && code) {
219*ae771770SStanislav Sedov 	krb5_set_error_message(context, code,
220*ae771770SStanislav Sedov 			       N_("scache execute %s: %s", ""), str,
221*ae771770SStanislav Sedov 			       sqlite3_errmsg(db));
222*ae771770SStanislav Sedov 	return code;
223*ae771770SStanislav Sedov     }
224*ae771770SStanislav Sedov     return 0;
225*ae771770SStanislav Sedov }
226*ae771770SStanislav Sedov 
227*ae771770SStanislav Sedov static krb5_error_code
default_db(krb5_context context,sqlite3 ** db)228*ae771770SStanislav Sedov default_db(krb5_context context, sqlite3 **db)
229*ae771770SStanislav Sedov {
230*ae771770SStanislav Sedov     char *name;
231*ae771770SStanislav Sedov     int ret;
232*ae771770SStanislav Sedov 
233*ae771770SStanislav Sedov     ret = _krb5_expand_default_cc_name(context, KRB5_SCACHE_DB, &name);
234*ae771770SStanislav Sedov     if (ret)
235*ae771770SStanislav Sedov 	return ret;
236*ae771770SStanislav Sedov 
237*ae771770SStanislav Sedov     ret = sqlite3_open_v2(name, db, SQLITE_OPEN_READWRITE, NULL);
238*ae771770SStanislav Sedov     free(name);
239*ae771770SStanislav Sedov     if (ret != SQLITE_OK) {
240*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
241*ae771770SStanislav Sedov 	return ENOENT;
242*ae771770SStanislav Sedov     }
243*ae771770SStanislav Sedov 
244*ae771770SStanislav Sedov #ifdef TRACEME
245*ae771770SStanislav Sedov     sqlite3_trace(*db, trace, NULL);
246*ae771770SStanislav Sedov #endif
247*ae771770SStanislav Sedov 
248*ae771770SStanislav Sedov     return 0;
249*ae771770SStanislav Sedov }
250*ae771770SStanislav Sedov 
251*ae771770SStanislav Sedov static krb5_error_code
get_def_name(krb5_context context,char ** str)252*ae771770SStanislav Sedov get_def_name(krb5_context context, char **str)
253*ae771770SStanislav Sedov {
254*ae771770SStanislav Sedov     krb5_error_code ret;
255*ae771770SStanislav Sedov     sqlite3_stmt *stmt;
256*ae771770SStanislav Sedov     const char *name;
257*ae771770SStanislav Sedov     sqlite3 *db;
258*ae771770SStanislav Sedov 
259*ae771770SStanislav Sedov     ret = default_db(context, &db);
260*ae771770SStanislav Sedov     if (ret)
261*ae771770SStanislav Sedov 	return ret;
262*ae771770SStanislav Sedov 
263*ae771770SStanislav Sedov     ret = prepare_stmt(context, db, &stmt, "SELECT defaultcache FROM master");
264*ae771770SStanislav Sedov     if (ret) {
265*ae771770SStanislav Sedov 	sqlite3_close(db);
266*ae771770SStanislav Sedov 	return ret;
267*ae771770SStanislav Sedov     }
268*ae771770SStanislav Sedov 
269*ae771770SStanislav Sedov     ret = sqlite3_step(stmt);
270*ae771770SStanislav Sedov     if (ret != SQLITE_ROW)
271*ae771770SStanislav Sedov 	goto out;
272*ae771770SStanislav Sedov 
273*ae771770SStanislav Sedov     if (sqlite3_column_type(stmt, 0) != SQLITE_TEXT)
274*ae771770SStanislav Sedov 	goto out;
275*ae771770SStanislav Sedov 
276*ae771770SStanislav Sedov     name = (const char *)sqlite3_column_text(stmt, 0);
277*ae771770SStanislav Sedov     if (name == NULL)
278*ae771770SStanislav Sedov 	goto out;
279*ae771770SStanislav Sedov 
280*ae771770SStanislav Sedov     *str = strdup(name);
281*ae771770SStanislav Sedov     if (*str == NULL)
282*ae771770SStanislav Sedov 	goto out;
283*ae771770SStanislav Sedov 
284*ae771770SStanislav Sedov     sqlite3_finalize(stmt);
285*ae771770SStanislav Sedov     sqlite3_close(db);
286*ae771770SStanislav Sedov     return 0;
287*ae771770SStanislav Sedov out:
288*ae771770SStanislav Sedov     sqlite3_finalize(stmt);
289*ae771770SStanislav Sedov     sqlite3_close(db);
290*ae771770SStanislav Sedov     krb5_clear_error_message(context);
291*ae771770SStanislav Sedov     return ENOENT;
292*ae771770SStanislav Sedov }
293*ae771770SStanislav Sedov 
294*ae771770SStanislav Sedov 
295*ae771770SStanislav Sedov 
296*ae771770SStanislav Sedov static krb5_scache * KRB5_CALLCONV
scc_alloc(krb5_context context,const char * name)297*ae771770SStanislav Sedov scc_alloc(krb5_context context, const char *name)
298*ae771770SStanislav Sedov {
299*ae771770SStanislav Sedov     krb5_error_code ret;
300*ae771770SStanislav Sedov     krb5_scache *s;
301*ae771770SStanislav Sedov 
302*ae771770SStanislav Sedov     ALLOC(s, 1);
303*ae771770SStanislav Sedov     if(s == NULL)
304*ae771770SStanislav Sedov 	return NULL;
305*ae771770SStanislav Sedov 
306*ae771770SStanislav Sedov     s->cid = SCACHE_INVALID_CID;
307*ae771770SStanislav Sedov 
308*ae771770SStanislav Sedov     if (name) {
309*ae771770SStanislav Sedov 	char *file;
310*ae771770SStanislav Sedov 
311*ae771770SStanislav Sedov 	if (*name == '\0') {
312*ae771770SStanislav Sedov 	    krb5_error_code ret;
313*ae771770SStanislav Sedov 	    ret = get_def_name(context, &s->name);
314*ae771770SStanislav Sedov 	    if (ret)
315*ae771770SStanislav Sedov 		s->name = strdup(SCACHE_DEF_NAME);
316*ae771770SStanislav Sedov 	} else
317*ae771770SStanislav Sedov 	    s->name = strdup(name);
318*ae771770SStanislav Sedov 
319*ae771770SStanislav Sedov 	file = strrchr(s->name, ':');
320*ae771770SStanislav Sedov 	if (file) {
321*ae771770SStanislav Sedov 	    *file++ = '\0';
322*ae771770SStanislav Sedov 	    s->file = strdup(file);
323*ae771770SStanislav Sedov 	    ret = 0;
324*ae771770SStanislav Sedov 	} else {
325*ae771770SStanislav Sedov 	    ret = _krb5_expand_default_cc_name(context, KRB5_SCACHE_DB, &s->file);
326*ae771770SStanislav Sedov 	}
327*ae771770SStanislav Sedov     } else {
328*ae771770SStanislav Sedov 	_krb5_expand_default_cc_name(context, KRB5_SCACHE_DB, &s->file);
329*ae771770SStanislav Sedov 	ret = asprintf(&s->name, "unique-%p", s);
330*ae771770SStanislav Sedov     }
331*ae771770SStanislav Sedov     if (ret < 0 || s->file == NULL || s->name == NULL) {
332*ae771770SStanislav Sedov 	scc_free(s);
333*ae771770SStanislav Sedov 	return NULL;
334*ae771770SStanislav Sedov     }
335*ae771770SStanislav Sedov 
336*ae771770SStanislav Sedov     return s;
337*ae771770SStanislav Sedov }
338*ae771770SStanislav Sedov 
339*ae771770SStanislav Sedov static krb5_error_code
open_database(krb5_context context,krb5_scache * s,int flags)340*ae771770SStanislav Sedov open_database(krb5_context context, krb5_scache *s, int flags)
341*ae771770SStanislav Sedov {
342*ae771770SStanislav Sedov     int ret;
343*ae771770SStanislav Sedov 
344*ae771770SStanislav Sedov     ret = sqlite3_open_v2(s->file, &s->db, SQLITE_OPEN_READWRITE|flags, NULL);
345*ae771770SStanislav Sedov     if (ret) {
346*ae771770SStanislav Sedov 	if (s->db) {
347*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ENOENT,
348*ae771770SStanislav Sedov 				   N_("Error opening scache file %s: %s", ""),
349*ae771770SStanislav Sedov 				   s->file, sqlite3_errmsg(s->db));
350*ae771770SStanislav Sedov 	    sqlite3_close(s->db);
351*ae771770SStanislav Sedov 	    s->db = NULL;
352*ae771770SStanislav Sedov 	} else
353*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ENOENT,
354*ae771770SStanislav Sedov 				   N_("malloc: out of memory", ""));
355*ae771770SStanislav Sedov 	return ENOENT;
356*ae771770SStanislav Sedov     }
357*ae771770SStanislav Sedov     return 0;
358*ae771770SStanislav Sedov }
359*ae771770SStanislav Sedov 
360*ae771770SStanislav Sedov static krb5_error_code
create_cache(krb5_context context,krb5_scache * s)361*ae771770SStanislav Sedov create_cache(krb5_context context, krb5_scache *s)
362*ae771770SStanislav Sedov {
363*ae771770SStanislav Sedov     int ret;
364*ae771770SStanislav Sedov 
365*ae771770SStanislav Sedov     sqlite3_bind_text(s->icache, 1, s->name, -1, NULL);
366*ae771770SStanislav Sedov     do {
367*ae771770SStanislav Sedov 	ret = sqlite3_step(s->icache);
368*ae771770SStanislav Sedov     } while (ret == SQLITE_ROW);
369*ae771770SStanislav Sedov     if (ret != SQLITE_DONE) {
370*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
371*ae771770SStanislav Sedov 			       N_("Failed to add scache: %d", ""), ret);
372*ae771770SStanislav Sedov 	return KRB5_CC_IO;
373*ae771770SStanislav Sedov     }
374*ae771770SStanislav Sedov     sqlite3_reset(s->icache);
375*ae771770SStanislav Sedov 
376*ae771770SStanislav Sedov     s->cid = sqlite3_last_insert_rowid(s->db);
377*ae771770SStanislav Sedov 
378*ae771770SStanislav Sedov     return 0;
379*ae771770SStanislav Sedov }
380*ae771770SStanislav Sedov 
381*ae771770SStanislav Sedov static krb5_error_code
make_database(krb5_context context,krb5_scache * s)382*ae771770SStanislav Sedov make_database(krb5_context context, krb5_scache *s)
383*ae771770SStanislav Sedov {
384*ae771770SStanislav Sedov     int created_file = 0;
385*ae771770SStanislav Sedov     int ret;
386*ae771770SStanislav Sedov 
387*ae771770SStanislav Sedov     if (s->db)
388*ae771770SStanislav Sedov 	return 0;
389*ae771770SStanislav Sedov 
390*ae771770SStanislav Sedov     ret = open_database(context, s, 0);
391*ae771770SStanislav Sedov     if (ret) {
392*ae771770SStanislav Sedov 	mode_t oldumask = umask(077);
393*ae771770SStanislav Sedov 	ret = open_database(context, s, SQLITE_OPEN_CREATE);
394*ae771770SStanislav Sedov 	umask(oldumask);
395*ae771770SStanislav Sedov 	if (ret) goto out;
396*ae771770SStanislav Sedov 
397*ae771770SStanislav Sedov 	created_file = 1;
398*ae771770SStanislav Sedov 
399*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_CMASTER, KRB5_CC_IO);
400*ae771770SStanislav Sedov 	if (ret) goto out;
401*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_CCACHE, KRB5_CC_IO);
402*ae771770SStanislav Sedov 	if (ret) goto out;
403*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_CCREDS, KRB5_CC_IO);
404*ae771770SStanislav Sedov 	if (ret) goto out;
405*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_CPRINCIPALS, KRB5_CC_IO);
406*ae771770SStanislav Sedov 	if (ret) goto out;
407*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_SETUP_MASTER, KRB5_CC_IO);
408*ae771770SStanislav Sedov 	if (ret) goto out;
409*ae771770SStanislav Sedov 
410*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_TCACHE, KRB5_CC_IO);
411*ae771770SStanislav Sedov 	if (ret) goto out;
412*ae771770SStanislav Sedov 	ret = exec_stmt(context, s->db, SQL_TCRED, KRB5_CC_IO);
413*ae771770SStanislav Sedov 	if (ret) goto out;
414*ae771770SStanislav Sedov     }
415*ae771770SStanislav Sedov 
416*ae771770SStanislav Sedov #ifdef TRACEME
417*ae771770SStanislav Sedov     sqlite3_trace(s->db, trace, NULL);
418*ae771770SStanislav Sedov #endif
419*ae771770SStanislav Sedov 
420*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->icred, SQL_ICRED);
421*ae771770SStanislav Sedov     if (ret) goto out;
422*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->dcred, SQL_DCRED);
423*ae771770SStanislav Sedov     if (ret) goto out;
424*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->iprincipal, SQL_IPRINCIPAL);
425*ae771770SStanislav Sedov     if (ret) goto out;
426*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->icache, SQL_ICACHE);
427*ae771770SStanislav Sedov     if (ret) goto out;
428*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->ucachen, SQL_UCACHE_NAME);
429*ae771770SStanislav Sedov     if (ret) goto out;
430*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->ucachep, SQL_UCACHE_PRINCIPAL);
431*ae771770SStanislav Sedov     if (ret) goto out;
432*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->dcache, SQL_DCACHE);
433*ae771770SStanislav Sedov     if (ret) goto out;
434*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->scache, SQL_SCACHE);
435*ae771770SStanislav Sedov     if (ret) goto out;
436*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->scache_name, SQL_SCACHE_NAME);
437*ae771770SStanislav Sedov     if (ret) goto out;
438*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &s->umaster, SQL_UMASTER);
439*ae771770SStanislav Sedov     if (ret) goto out;
440*ae771770SStanislav Sedov 
441*ae771770SStanislav Sedov     return 0;
442*ae771770SStanislav Sedov 
443*ae771770SStanislav Sedov out:
444*ae771770SStanislav Sedov     if (s->db)
445*ae771770SStanislav Sedov 	sqlite3_close(s->db);
446*ae771770SStanislav Sedov     if (created_file)
447*ae771770SStanislav Sedov 	unlink(s->file);
448*ae771770SStanislav Sedov 
449*ae771770SStanislav Sedov     return ret;
450*ae771770SStanislav Sedov }
451*ae771770SStanislav Sedov 
452*ae771770SStanislav Sedov static krb5_error_code
bind_principal(krb5_context context,sqlite3 * db,sqlite3_stmt * stmt,int col,krb5_const_principal principal)453*ae771770SStanislav Sedov bind_principal(krb5_context context,
454*ae771770SStanislav Sedov 	       sqlite3 *db,
455*ae771770SStanislav Sedov 	       sqlite3_stmt *stmt,
456*ae771770SStanislav Sedov 	       int col,
457*ae771770SStanislav Sedov 	       krb5_const_principal principal)
458*ae771770SStanislav Sedov {
459*ae771770SStanislav Sedov     krb5_error_code ret;
460*ae771770SStanislav Sedov     char *str;
461*ae771770SStanislav Sedov 
462*ae771770SStanislav Sedov     ret = krb5_unparse_name(context, principal, &str);
463*ae771770SStanislav Sedov     if (ret)
464*ae771770SStanislav Sedov 	return ret;
465*ae771770SStanislav Sedov 
466*ae771770SStanislav Sedov     ret = sqlite3_bind_text(stmt, col, str, -1, free_krb5);
467*ae771770SStanislav Sedov     if (ret != SQLITE_OK) {
468*ae771770SStanislav Sedov 	krb5_xfree(str);
469*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
470*ae771770SStanislav Sedov 			       N_("scache bind principal: %s", ""),
471*ae771770SStanislav Sedov 			       sqlite3_errmsg(db));
472*ae771770SStanislav Sedov 	return ENOMEM;
473*ae771770SStanislav Sedov     }
474*ae771770SStanislav Sedov     return 0;
475*ae771770SStanislav Sedov }
476*ae771770SStanislav Sedov 
477*ae771770SStanislav Sedov /*
478*ae771770SStanislav Sedov  *
479*ae771770SStanislav Sedov  */
480*ae771770SStanislav Sedov 
481*ae771770SStanislav Sedov static const char* KRB5_CALLCONV
scc_get_name(krb5_context context,krb5_ccache id)482*ae771770SStanislav Sedov scc_get_name(krb5_context context,
483*ae771770SStanislav Sedov 	     krb5_ccache id)
484*ae771770SStanislav Sedov {
485*ae771770SStanislav Sedov     return SCACHE(id)->name;
486*ae771770SStanislav Sedov }
487*ae771770SStanislav Sedov 
488*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_resolve(krb5_context context,krb5_ccache * id,const char * res)489*ae771770SStanislav Sedov scc_resolve(krb5_context context, krb5_ccache *id, const char *res)
490*ae771770SStanislav Sedov {
491*ae771770SStanislav Sedov     krb5_scache *s;
492*ae771770SStanislav Sedov     int ret;
493*ae771770SStanislav Sedov 
494*ae771770SStanislav Sedov     s = scc_alloc(context, res);
495*ae771770SStanislav Sedov     if (s == NULL) {
496*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_NOMEM,
497*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
498*ae771770SStanislav Sedov 	return KRB5_CC_NOMEM;
499*ae771770SStanislav Sedov     }
500*ae771770SStanislav Sedov 
501*ae771770SStanislav Sedov     ret = make_database(context, s);
502*ae771770SStanislav Sedov     if (ret) {
503*ae771770SStanislav Sedov 	scc_free(s);
504*ae771770SStanislav Sedov 	return ret;
505*ae771770SStanislav Sedov     }
506*ae771770SStanislav Sedov 
507*ae771770SStanislav Sedov     ret = sqlite3_bind_text(s->scache_name, 1, s->name, -1, NULL);
508*ae771770SStanislav Sedov     if (ret != SQLITE_OK) {
509*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
510*ae771770SStanislav Sedov 			       "bind name: %s", sqlite3_errmsg(s->db));
511*ae771770SStanislav Sedov 	scc_free(s);
512*ae771770SStanislav Sedov 	return ENOMEM;
513*ae771770SStanislav Sedov     }
514*ae771770SStanislav Sedov 
515*ae771770SStanislav Sedov     if (sqlite3_step(s->scache_name) == SQLITE_ROW) {
516*ae771770SStanislav Sedov 
517*ae771770SStanislav Sedov 	if (sqlite3_column_type(s->scache_name, 0) != SQLITE_INTEGER) {
518*ae771770SStanislav Sedov 	    sqlite3_reset(s->scache_name);
519*ae771770SStanislav Sedov 	    krb5_set_error_message(context, KRB5_CC_END,
520*ae771770SStanislav Sedov 				   N_("Cache name of wrong type "
521*ae771770SStanislav Sedov 				      "for scache %s", ""),
522*ae771770SStanislav Sedov 				   s->name);
523*ae771770SStanislav Sedov 	    scc_free(s);
524*ae771770SStanislav Sedov 	    return KRB5_CC_END;
525*ae771770SStanislav Sedov 	}
526*ae771770SStanislav Sedov 
527*ae771770SStanislav Sedov 	s->cid = sqlite3_column_int(s->scache_name, 0);
528*ae771770SStanislav Sedov     } else {
529*ae771770SStanislav Sedov 	s->cid = SCACHE_INVALID_CID;
530*ae771770SStanislav Sedov     }
531*ae771770SStanislav Sedov     sqlite3_reset(s->scache_name);
532*ae771770SStanislav Sedov 
533*ae771770SStanislav Sedov     (*id)->data.data = s;
534*ae771770SStanislav Sedov     (*id)->data.length = sizeof(*s);
535*ae771770SStanislav Sedov 
536*ae771770SStanislav Sedov     return 0;
537*ae771770SStanislav Sedov }
538*ae771770SStanislav Sedov 
539*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_gen_new(krb5_context context,krb5_ccache * id)540*ae771770SStanislav Sedov scc_gen_new(krb5_context context, krb5_ccache *id)
541*ae771770SStanislav Sedov {
542*ae771770SStanislav Sedov     krb5_scache *s;
543*ae771770SStanislav Sedov 
544*ae771770SStanislav Sedov     s = scc_alloc(context, NULL);
545*ae771770SStanislav Sedov 
546*ae771770SStanislav Sedov     if (s == NULL) {
547*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_NOMEM,
548*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
549*ae771770SStanislav Sedov 	return KRB5_CC_NOMEM;
550*ae771770SStanislav Sedov     }
551*ae771770SStanislav Sedov 
552*ae771770SStanislav Sedov     (*id)->data.data = s;
553*ae771770SStanislav Sedov     (*id)->data.length = sizeof(*s);
554*ae771770SStanislav Sedov 
555*ae771770SStanislav Sedov     return 0;
556*ae771770SStanislav Sedov }
557*ae771770SStanislav Sedov 
558*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_initialize(krb5_context context,krb5_ccache id,krb5_principal primary_principal)559*ae771770SStanislav Sedov scc_initialize(krb5_context context,
560*ae771770SStanislav Sedov 	       krb5_ccache id,
561*ae771770SStanislav Sedov 	       krb5_principal primary_principal)
562*ae771770SStanislav Sedov {
563*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
564*ae771770SStanislav Sedov     krb5_error_code ret;
565*ae771770SStanislav Sedov 
566*ae771770SStanislav Sedov     ret = make_database(context, s);
567*ae771770SStanislav Sedov     if (ret)
568*ae771770SStanislav Sedov 	return ret;
569*ae771770SStanislav Sedov 
570*ae771770SStanislav Sedov     ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO);
571*ae771770SStanislav Sedov     if (ret) return ret;
572*ae771770SStanislav Sedov 
573*ae771770SStanislav Sedov     if (s->cid == SCACHE_INVALID_CID) {
574*ae771770SStanislav Sedov 	ret = create_cache(context, s);
575*ae771770SStanislav Sedov 	if (ret)
576*ae771770SStanislav Sedov 	    goto rollback;
577*ae771770SStanislav Sedov     } else {
578*ae771770SStanislav Sedov 	sqlite3_bind_int(s->dcred, 1, s->cid);
579*ae771770SStanislav Sedov 	do {
580*ae771770SStanislav Sedov 	    ret = sqlite3_step(s->dcred);
581*ae771770SStanislav Sedov 	} while (ret == SQLITE_ROW);
582*ae771770SStanislav Sedov 	sqlite3_reset(s->dcred);
583*ae771770SStanislav Sedov 	if (ret != SQLITE_DONE) {
584*ae771770SStanislav Sedov 	    ret = KRB5_CC_IO;
585*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
586*ae771770SStanislav Sedov 				   N_("Failed to delete old "
587*ae771770SStanislav Sedov 				      "credentials: %s", ""),
588*ae771770SStanislav Sedov 				   sqlite3_errmsg(s->db));
589*ae771770SStanislav Sedov 	    goto rollback;
590*ae771770SStanislav Sedov 	}
591*ae771770SStanislav Sedov     }
592*ae771770SStanislav Sedov 
593*ae771770SStanislav Sedov     ret = bind_principal(context, s->db, s->ucachep, 1, primary_principal);
594*ae771770SStanislav Sedov     if (ret)
595*ae771770SStanislav Sedov 	goto rollback;
596*ae771770SStanislav Sedov     sqlite3_bind_int(s->ucachep, 2, s->cid);
597*ae771770SStanislav Sedov 
598*ae771770SStanislav Sedov     do {
599*ae771770SStanislav Sedov 	ret = sqlite3_step(s->ucachep);
600*ae771770SStanislav Sedov     } while (ret == SQLITE_ROW);
601*ae771770SStanislav Sedov     sqlite3_reset(s->ucachep);
602*ae771770SStanislav Sedov     if (ret != SQLITE_DONE) {
603*ae771770SStanislav Sedov 	ret = KRB5_CC_IO;
604*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
605*ae771770SStanislav Sedov 			       N_("Failed to bind principal to cache %s", ""),
606*ae771770SStanislav Sedov 			       sqlite3_errmsg(s->db));
607*ae771770SStanislav Sedov 	goto rollback;
608*ae771770SStanislav Sedov     }
609*ae771770SStanislav Sedov 
610*ae771770SStanislav Sedov     ret = exec_stmt(context, s->db, "COMMIT", KRB5_CC_IO);
611*ae771770SStanislav Sedov     if (ret) return ret;
612*ae771770SStanislav Sedov 
613*ae771770SStanislav Sedov     return 0;
614*ae771770SStanislav Sedov 
615*ae771770SStanislav Sedov rollback:
616*ae771770SStanislav Sedov     exec_stmt(context, s->db, "ROLLBACK", 0);
617*ae771770SStanislav Sedov 
618*ae771770SStanislav Sedov     return ret;
619*ae771770SStanislav Sedov 
620*ae771770SStanislav Sedov }
621*ae771770SStanislav Sedov 
622*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_close(krb5_context context,krb5_ccache id)623*ae771770SStanislav Sedov scc_close(krb5_context context,
624*ae771770SStanislav Sedov 	  krb5_ccache id)
625*ae771770SStanislav Sedov {
626*ae771770SStanislav Sedov     scc_free(SCACHE(id));
627*ae771770SStanislav Sedov     return 0;
628*ae771770SStanislav Sedov }
629*ae771770SStanislav Sedov 
630*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_destroy(krb5_context context,krb5_ccache id)631*ae771770SStanislav Sedov scc_destroy(krb5_context context,
632*ae771770SStanislav Sedov 	    krb5_ccache id)
633*ae771770SStanislav Sedov {
634*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
635*ae771770SStanislav Sedov     int ret;
636*ae771770SStanislav Sedov 
637*ae771770SStanislav Sedov     if (s->cid == SCACHE_INVALID_CID)
638*ae771770SStanislav Sedov 	return 0;
639*ae771770SStanislav Sedov 
640*ae771770SStanislav Sedov     sqlite3_bind_int(s->dcache, 1, s->cid);
641*ae771770SStanislav Sedov     do {
642*ae771770SStanislav Sedov 	ret = sqlite3_step(s->dcache);
643*ae771770SStanislav Sedov     } while (ret == SQLITE_ROW);
644*ae771770SStanislav Sedov     sqlite3_reset(s->dcache);
645*ae771770SStanislav Sedov     if (ret != SQLITE_DONE) {
646*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
647*ae771770SStanislav Sedov 			       N_("Failed to destroy cache %s: %s", ""),
648*ae771770SStanislav Sedov 			       s->name, sqlite3_errmsg(s->db));
649*ae771770SStanislav Sedov 	return KRB5_CC_IO;
650*ae771770SStanislav Sedov     }
651*ae771770SStanislav Sedov     return 0;
652*ae771770SStanislav Sedov }
653*ae771770SStanislav Sedov 
654*ae771770SStanislav Sedov static krb5_error_code
encode_creds(krb5_context context,krb5_creds * creds,krb5_data * data)655*ae771770SStanislav Sedov encode_creds(krb5_context context, krb5_creds *creds, krb5_data *data)
656*ae771770SStanislav Sedov {
657*ae771770SStanislav Sedov     krb5_error_code ret;
658*ae771770SStanislav Sedov     krb5_storage *sp;
659*ae771770SStanislav Sedov 
660*ae771770SStanislav Sedov     sp = krb5_storage_emem();
661*ae771770SStanislav Sedov     if (sp == NULL) {
662*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
663*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
664*ae771770SStanislav Sedov 	return ENOMEM;
665*ae771770SStanislav Sedov     }
666*ae771770SStanislav Sedov 
667*ae771770SStanislav Sedov     ret = krb5_store_creds(sp, creds);
668*ae771770SStanislav Sedov     if (ret) {
669*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
670*ae771770SStanislav Sedov 			       N_("Failed to store credential in scache", ""));
671*ae771770SStanislav Sedov 	krb5_storage_free(sp);
672*ae771770SStanislav Sedov 	return ret;
673*ae771770SStanislav Sedov     }
674*ae771770SStanislav Sedov 
675*ae771770SStanislav Sedov     ret = krb5_storage_to_data(sp, data);
676*ae771770SStanislav Sedov     krb5_storage_free(sp);
677*ae771770SStanislav Sedov     if (ret)
678*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
679*ae771770SStanislav Sedov 			       N_("Failed to encode credential in scache", ""));
680*ae771770SStanislav Sedov     return ret;
681*ae771770SStanislav Sedov }
682*ae771770SStanislav Sedov 
683*ae771770SStanislav Sedov static krb5_error_code
decode_creds(krb5_context context,const void * data,size_t length,krb5_creds * creds)684*ae771770SStanislav Sedov decode_creds(krb5_context context, const void *data, size_t length,
685*ae771770SStanislav Sedov 	     krb5_creds *creds)
686*ae771770SStanislav Sedov {
687*ae771770SStanislav Sedov     krb5_error_code ret;
688*ae771770SStanislav Sedov     krb5_storage *sp;
689*ae771770SStanislav Sedov 
690*ae771770SStanislav Sedov     sp = krb5_storage_from_readonly_mem(data, length);
691*ae771770SStanislav Sedov     if (sp == NULL) {
692*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
693*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
694*ae771770SStanislav Sedov 	return ENOMEM;
695*ae771770SStanislav Sedov     }
696*ae771770SStanislav Sedov 
697*ae771770SStanislav Sedov     ret = krb5_ret_creds(sp, creds);
698*ae771770SStanislav Sedov     krb5_storage_free(sp);
699*ae771770SStanislav Sedov     if (ret) {
700*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
701*ae771770SStanislav Sedov 			       N_("Failed to read credential in scache", ""));
702*ae771770SStanislav Sedov 	return ret;
703*ae771770SStanislav Sedov     }
704*ae771770SStanislav Sedov     return 0;
705*ae771770SStanislav Sedov }
706*ae771770SStanislav Sedov 
707*ae771770SStanislav Sedov 
708*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_store_cred(krb5_context context,krb5_ccache id,krb5_creds * creds)709*ae771770SStanislav Sedov scc_store_cred(krb5_context context,
710*ae771770SStanislav Sedov 	       krb5_ccache id,
711*ae771770SStanislav Sedov 	       krb5_creds *creds)
712*ae771770SStanislav Sedov {
713*ae771770SStanislav Sedov     sqlite_uint64 credid;
714*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
715*ae771770SStanislav Sedov     krb5_error_code ret;
716*ae771770SStanislav Sedov     krb5_data data;
717*ae771770SStanislav Sedov 
718*ae771770SStanislav Sedov     ret = make_database(context, s);
719*ae771770SStanislav Sedov     if (ret)
720*ae771770SStanislav Sedov 	return ret;
721*ae771770SStanislav Sedov 
722*ae771770SStanislav Sedov     ret = encode_creds(context, creds, &data);
723*ae771770SStanislav Sedov     if (ret)
724*ae771770SStanislav Sedov 	return ret;
725*ae771770SStanislav Sedov 
726*ae771770SStanislav Sedov     sqlite3_bind_int(s->icred, 1, s->cid);
727*ae771770SStanislav Sedov     {
728*ae771770SStanislav Sedov 	krb5_enctype etype = 0;
729*ae771770SStanislav Sedov 	int kvno = 0;
730*ae771770SStanislav Sedov 	Ticket t;
731*ae771770SStanislav Sedov 	size_t len;
732*ae771770SStanislav Sedov 
733*ae771770SStanislav Sedov 	ret = decode_Ticket(creds->ticket.data,
734*ae771770SStanislav Sedov 			    creds->ticket.length, &t, &len);
735*ae771770SStanislav Sedov 	if (ret == 0) {
736*ae771770SStanislav Sedov 	    if(t.enc_part.kvno)
737*ae771770SStanislav Sedov 		kvno = *t.enc_part.kvno;
738*ae771770SStanislav Sedov 
739*ae771770SStanislav Sedov 	    etype = t.enc_part.etype;
740*ae771770SStanislav Sedov 
741*ae771770SStanislav Sedov 	    free_Ticket(&t);
742*ae771770SStanislav Sedov 	}
743*ae771770SStanislav Sedov 
744*ae771770SStanislav Sedov 	sqlite3_bind_int(s->icred, 2, kvno);
745*ae771770SStanislav Sedov 	sqlite3_bind_int(s->icred, 3, etype);
746*ae771770SStanislav Sedov 
747*ae771770SStanislav Sedov     }
748*ae771770SStanislav Sedov 
749*ae771770SStanislav Sedov     sqlite3_bind_blob(s->icred, 4, data.data, data.length, free_data);
750*ae771770SStanislav Sedov     sqlite3_bind_int(s->icred, 5, time(NULL));
751*ae771770SStanislav Sedov 
752*ae771770SStanislav Sedov     ret = exec_stmt(context, s->db, "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO);
753*ae771770SStanislav Sedov     if (ret) return ret;
754*ae771770SStanislav Sedov 
755*ae771770SStanislav Sedov     do {
756*ae771770SStanislav Sedov 	ret = sqlite3_step(s->icred);
757*ae771770SStanislav Sedov     } while (ret == SQLITE_ROW);
758*ae771770SStanislav Sedov     sqlite3_reset(s->icred);
759*ae771770SStanislav Sedov     if (ret != SQLITE_DONE) {
760*ae771770SStanislav Sedov 	ret = KRB5_CC_IO;
761*ae771770SStanislav Sedov 	krb5_set_error_message(context, ret,
762*ae771770SStanislav Sedov 			       N_("Failed to add credential: %s", ""),
763*ae771770SStanislav Sedov 			       sqlite3_errmsg(s->db));
764*ae771770SStanislav Sedov 	goto rollback;
765*ae771770SStanislav Sedov     }
766*ae771770SStanislav Sedov 
767*ae771770SStanislav Sedov     credid = sqlite3_last_insert_rowid(s->db);
768*ae771770SStanislav Sedov 
769*ae771770SStanislav Sedov     {
770*ae771770SStanislav Sedov 	bind_principal(context, s->db, s->iprincipal, 1, creds->server);
771*ae771770SStanislav Sedov 	sqlite3_bind_int(s->iprincipal, 2, 1);
772*ae771770SStanislav Sedov 	sqlite3_bind_int(s->iprincipal, 3, credid);
773*ae771770SStanislav Sedov 
774*ae771770SStanislav Sedov 	do {
775*ae771770SStanislav Sedov 	    ret = sqlite3_step(s->iprincipal);
776*ae771770SStanislav Sedov 	} while (ret == SQLITE_ROW);
777*ae771770SStanislav Sedov 	sqlite3_reset(s->iprincipal);
778*ae771770SStanislav Sedov 	if (ret != SQLITE_DONE) {
779*ae771770SStanislav Sedov 	    ret = KRB5_CC_IO;
780*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
781*ae771770SStanislav Sedov 				   N_("Failed to add principal: %s", ""),
782*ae771770SStanislav Sedov 				   sqlite3_errmsg(s->db));
783*ae771770SStanislav Sedov 	    goto rollback;
784*ae771770SStanislav Sedov 	}
785*ae771770SStanislav Sedov     }
786*ae771770SStanislav Sedov 
787*ae771770SStanislav Sedov     {
788*ae771770SStanislav Sedov 	bind_principal(context, s->db, s->iprincipal, 1, creds->client);
789*ae771770SStanislav Sedov 	sqlite3_bind_int(s->iprincipal, 2, 0);
790*ae771770SStanislav Sedov 	sqlite3_bind_int(s->iprincipal, 3, credid);
791*ae771770SStanislav Sedov 
792*ae771770SStanislav Sedov 	do {
793*ae771770SStanislav Sedov 	    ret = sqlite3_step(s->iprincipal);
794*ae771770SStanislav Sedov 	} while (ret == SQLITE_ROW);
795*ae771770SStanislav Sedov 	sqlite3_reset(s->iprincipal);
796*ae771770SStanislav Sedov 	if (ret != SQLITE_DONE) {
797*ae771770SStanislav Sedov 	    ret = KRB5_CC_IO;
798*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
799*ae771770SStanislav Sedov 				   N_("Failed to add principal: %s", ""),
800*ae771770SStanislav Sedov 				   sqlite3_errmsg(s->db));
801*ae771770SStanislav Sedov 	    goto rollback;
802*ae771770SStanislav Sedov 	}
803*ae771770SStanislav Sedov     }
804*ae771770SStanislav Sedov 
805*ae771770SStanislav Sedov     ret = exec_stmt(context, s->db, "COMMIT", KRB5_CC_IO);
806*ae771770SStanislav Sedov     if (ret) return ret;
807*ae771770SStanislav Sedov 
808*ae771770SStanislav Sedov     return 0;
809*ae771770SStanislav Sedov 
810*ae771770SStanislav Sedov rollback:
811*ae771770SStanislav Sedov     exec_stmt(context, s->db, "ROLLBACK", 0);
812*ae771770SStanislav Sedov 
813*ae771770SStanislav Sedov     return ret;
814*ae771770SStanislav Sedov }
815*ae771770SStanislav Sedov 
816*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_get_principal(krb5_context context,krb5_ccache id,krb5_principal * principal)817*ae771770SStanislav Sedov scc_get_principal(krb5_context context,
818*ae771770SStanislav Sedov 		  krb5_ccache id,
819*ae771770SStanislav Sedov 		  krb5_principal *principal)
820*ae771770SStanislav Sedov {
821*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
822*ae771770SStanislav Sedov     krb5_error_code ret;
823*ae771770SStanislav Sedov     const char *str;
824*ae771770SStanislav Sedov 
825*ae771770SStanislav Sedov     *principal = NULL;
826*ae771770SStanislav Sedov 
827*ae771770SStanislav Sedov     ret = make_database(context, s);
828*ae771770SStanislav Sedov     if (ret)
829*ae771770SStanislav Sedov 	return ret;
830*ae771770SStanislav Sedov 
831*ae771770SStanislav Sedov     sqlite3_bind_int(s->scache, 1, s->cid);
832*ae771770SStanislav Sedov 
833*ae771770SStanislav Sedov     if (sqlite3_step(s->scache) != SQLITE_ROW) {
834*ae771770SStanislav Sedov 	sqlite3_reset(s->scache);
835*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_END,
836*ae771770SStanislav Sedov 			       N_("No principal for cache SCC:%s:%s", ""),
837*ae771770SStanislav Sedov 			       s->name, s->file);
838*ae771770SStanislav Sedov 	return KRB5_CC_END;
839*ae771770SStanislav Sedov     }
840*ae771770SStanislav Sedov 
841*ae771770SStanislav Sedov     if (sqlite3_column_type(s->scache, 0) != SQLITE_TEXT) {
842*ae771770SStanislav Sedov 	sqlite3_reset(s->scache);
843*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_END,
844*ae771770SStanislav Sedov 			       N_("Principal data of wrong type "
845*ae771770SStanislav Sedov 				  "for SCC:%s:%s", ""),
846*ae771770SStanislav Sedov 			       s->name, s->file);
847*ae771770SStanislav Sedov 	return KRB5_CC_END;
848*ae771770SStanislav Sedov     }
849*ae771770SStanislav Sedov 
850*ae771770SStanislav Sedov     str = (const char *)sqlite3_column_text(s->scache, 0);
851*ae771770SStanislav Sedov     if (str == NULL) {
852*ae771770SStanislav Sedov 	sqlite3_reset(s->scache);
853*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_END,
854*ae771770SStanislav Sedov 			       N_("Principal not set for SCC:%s:%s", ""),
855*ae771770SStanislav Sedov 			       s->name, s->file);
856*ae771770SStanislav Sedov 	return KRB5_CC_END;
857*ae771770SStanislav Sedov     }
858*ae771770SStanislav Sedov 
859*ae771770SStanislav Sedov     ret = krb5_parse_name(context, str, principal);
860*ae771770SStanislav Sedov 
861*ae771770SStanislav Sedov     sqlite3_reset(s->scache);
862*ae771770SStanislav Sedov 
863*ae771770SStanislav Sedov     return ret;
864*ae771770SStanislav Sedov }
865*ae771770SStanislav Sedov 
866*ae771770SStanislav Sedov struct cred_ctx {
867*ae771770SStanislav Sedov     char *drop;
868*ae771770SStanislav Sedov     sqlite3_stmt *stmt;
869*ae771770SStanislav Sedov     sqlite3_stmt *credstmt;
870*ae771770SStanislav Sedov };
871*ae771770SStanislav Sedov 
872*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_get_first(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)873*ae771770SStanislav Sedov scc_get_first (krb5_context context,
874*ae771770SStanislav Sedov 	       krb5_ccache id,
875*ae771770SStanislav Sedov 	       krb5_cc_cursor *cursor)
876*ae771770SStanislav Sedov {
877*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
878*ae771770SStanislav Sedov     krb5_error_code ret;
879*ae771770SStanislav Sedov     struct cred_ctx *ctx;
880*ae771770SStanislav Sedov     char *str = NULL, *name = NULL;
881*ae771770SStanislav Sedov 
882*ae771770SStanislav Sedov     *cursor = NULL;
883*ae771770SStanislav Sedov 
884*ae771770SStanislav Sedov     ctx = calloc(1, sizeof(*ctx));
885*ae771770SStanislav Sedov     if (ctx == NULL) {
886*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
887*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
888*ae771770SStanislav Sedov 	return ENOMEM;
889*ae771770SStanislav Sedov     }
890*ae771770SStanislav Sedov 
891*ae771770SStanislav Sedov     ret = make_database(context, s);
892*ae771770SStanislav Sedov     if (ret) {
893*ae771770SStanislav Sedov 	free(ctx);
894*ae771770SStanislav Sedov 	return ret;
895*ae771770SStanislav Sedov     }
896*ae771770SStanislav Sedov 
897*ae771770SStanislav Sedov     if (s->cid == SCACHE_INVALID_CID) {
898*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_END,
899*ae771770SStanislav Sedov 			       N_("Iterating a invalid scache %s", ""),
900*ae771770SStanislav Sedov 			       s->name);
901*ae771770SStanislav Sedov 	free(ctx);
902*ae771770SStanislav Sedov 	return KRB5_CC_END;
903*ae771770SStanislav Sedov     }
904*ae771770SStanislav Sedov 
905*ae771770SStanislav Sedov     ret = asprintf(&name, "credIteration%pPid%d",
906*ae771770SStanislav Sedov                    ctx, (int)getpid());
907*ae771770SStanislav Sedov     if (ret < 0 || name == NULL) {
908*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
909*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
910*ae771770SStanislav Sedov 	free(ctx);
911*ae771770SStanislav Sedov 	return ENOMEM;
912*ae771770SStanislav Sedov     }
913*ae771770SStanislav Sedov 
914*ae771770SStanislav Sedov     ret = asprintf(&ctx->drop, "DROP TABLE %s", name);
915*ae771770SStanislav Sedov     if (ret < 0 || ctx->drop == NULL) {
916*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
917*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
918*ae771770SStanislav Sedov 	free(name);
919*ae771770SStanislav Sedov 	free(ctx);
920*ae771770SStanislav Sedov 	return ENOMEM;
921*ae771770SStanislav Sedov     }
922*ae771770SStanislav Sedov 
923*ae771770SStanislav Sedov     ret = asprintf(&str, "CREATE TEMPORARY TABLE %s "
924*ae771770SStanislav Sedov 	     "AS SELECT oid,created_at FROM credentials WHERE cid = %lu",
925*ae771770SStanislav Sedov 	     name, (unsigned long)s->cid);
926*ae771770SStanislav Sedov     if (ret < 0 || str == NULL) {
927*ae771770SStanislav Sedov 	free(ctx->drop);
928*ae771770SStanislav Sedov 	free(name);
929*ae771770SStanislav Sedov 	free(ctx);
930*ae771770SStanislav Sedov 	return ENOMEM;
931*ae771770SStanislav Sedov     }
932*ae771770SStanislav Sedov 
933*ae771770SStanislav Sedov     ret = exec_stmt(context, s->db, str, KRB5_CC_IO);
934*ae771770SStanislav Sedov     free(str);
935*ae771770SStanislav Sedov     str = NULL;
936*ae771770SStanislav Sedov     if (ret) {
937*ae771770SStanislav Sedov 	free(ctx->drop);
938*ae771770SStanislav Sedov 	free(name);
939*ae771770SStanislav Sedov 	free(ctx);
940*ae771770SStanislav Sedov 	return ret;
941*ae771770SStanislav Sedov     }
942*ae771770SStanislav Sedov 
943*ae771770SStanislav Sedov     ret = asprintf(&str, "SELECT oid FROM %s ORDER BY created_at", name);
944*ae771770SStanislav Sedov     if (ret < 0 || str == NULL) {
945*ae771770SStanislav Sedov 	exec_stmt(context, s->db, ctx->drop, 0);
946*ae771770SStanislav Sedov 	free(ctx->drop);
947*ae771770SStanislav Sedov 	free(name);
948*ae771770SStanislav Sedov 	free(ctx);
949*ae771770SStanislav Sedov 	return ret;
950*ae771770SStanislav Sedov     }
951*ae771770SStanislav Sedov 
952*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &ctx->stmt, str);
953*ae771770SStanislav Sedov     free(str);
954*ae771770SStanislav Sedov     str = NULL;
955*ae771770SStanislav Sedov     free(name);
956*ae771770SStanislav Sedov     if (ret) {
957*ae771770SStanislav Sedov 	exec_stmt(context, s->db, ctx->drop, 0);
958*ae771770SStanislav Sedov 	free(ctx->drop);
959*ae771770SStanislav Sedov 	free(ctx);
960*ae771770SStanislav Sedov 	return ret;
961*ae771770SStanislav Sedov     }
962*ae771770SStanislav Sedov 
963*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &ctx->credstmt,
964*ae771770SStanislav Sedov 		       "SELECT cred FROM credentials WHERE oid = ?");
965*ae771770SStanislav Sedov     if (ret) {
966*ae771770SStanislav Sedov 	sqlite3_finalize(ctx->stmt);
967*ae771770SStanislav Sedov 	exec_stmt(context, s->db, ctx->drop, 0);
968*ae771770SStanislav Sedov 	free(ctx->drop);
969*ae771770SStanislav Sedov 	free(ctx);
970*ae771770SStanislav Sedov 	return ret;
971*ae771770SStanislav Sedov     }
972*ae771770SStanislav Sedov 
973*ae771770SStanislav Sedov     *cursor = ctx;
974*ae771770SStanislav Sedov 
975*ae771770SStanislav Sedov     return 0;
976*ae771770SStanislav Sedov }
977*ae771770SStanislav Sedov 
978*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_get_next(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor,krb5_creds * creds)979*ae771770SStanislav Sedov scc_get_next (krb5_context context,
980*ae771770SStanislav Sedov 	      krb5_ccache id,
981*ae771770SStanislav Sedov 	      krb5_cc_cursor *cursor,
982*ae771770SStanislav Sedov 	      krb5_creds *creds)
983*ae771770SStanislav Sedov {
984*ae771770SStanislav Sedov     struct cred_ctx *ctx = *cursor;
985*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
986*ae771770SStanislav Sedov     krb5_error_code ret;
987*ae771770SStanislav Sedov     sqlite_uint64 oid;
988*ae771770SStanislav Sedov     const void *data = NULL;
989*ae771770SStanislav Sedov     size_t len = 0;
990*ae771770SStanislav Sedov 
991*ae771770SStanislav Sedov next:
992*ae771770SStanislav Sedov     ret = sqlite3_step(ctx->stmt);
993*ae771770SStanislav Sedov     if (ret == SQLITE_DONE) {
994*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
995*ae771770SStanislav Sedov         return KRB5_CC_END;
996*ae771770SStanislav Sedov     } else if (ret != SQLITE_ROW) {
997*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
998*ae771770SStanislav Sedov 			       N_("scache Database failed: %s", ""),
999*ae771770SStanislav Sedov 			       sqlite3_errmsg(s->db));
1000*ae771770SStanislav Sedov         return KRB5_CC_IO;
1001*ae771770SStanislav Sedov     }
1002*ae771770SStanislav Sedov 
1003*ae771770SStanislav Sedov     oid = sqlite3_column_int64(ctx->stmt, 0);
1004*ae771770SStanislav Sedov 
1005*ae771770SStanislav Sedov     /* read cred from credentials table */
1006*ae771770SStanislav Sedov 
1007*ae771770SStanislav Sedov     sqlite3_bind_int(ctx->credstmt, 1, oid);
1008*ae771770SStanislav Sedov 
1009*ae771770SStanislav Sedov     ret = sqlite3_step(ctx->credstmt);
1010*ae771770SStanislav Sedov     if (ret != SQLITE_ROW) {
1011*ae771770SStanislav Sedov 	sqlite3_reset(ctx->credstmt);
1012*ae771770SStanislav Sedov 	goto next;
1013*ae771770SStanislav Sedov     }
1014*ae771770SStanislav Sedov 
1015*ae771770SStanislav Sedov     if (sqlite3_column_type(ctx->credstmt, 0) != SQLITE_BLOB) {
1016*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_END,
1017*ae771770SStanislav Sedov 			       N_("credential of wrong type for SCC:%s:%s", ""),
1018*ae771770SStanislav Sedov 			       s->name, s->file);
1019*ae771770SStanislav Sedov 	sqlite3_reset(ctx->credstmt);
1020*ae771770SStanislav Sedov 	return KRB5_CC_END;
1021*ae771770SStanislav Sedov     }
1022*ae771770SStanislav Sedov 
1023*ae771770SStanislav Sedov     data = sqlite3_column_blob(ctx->credstmt, 0);
1024*ae771770SStanislav Sedov     len = sqlite3_column_bytes(ctx->credstmt, 0);
1025*ae771770SStanislav Sedov 
1026*ae771770SStanislav Sedov     ret = decode_creds(context, data, len, creds);
1027*ae771770SStanislav Sedov     sqlite3_reset(ctx->credstmt);
1028*ae771770SStanislav Sedov     return ret;
1029*ae771770SStanislav Sedov }
1030*ae771770SStanislav Sedov 
1031*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_end_get(krb5_context context,krb5_ccache id,krb5_cc_cursor * cursor)1032*ae771770SStanislav Sedov scc_end_get (krb5_context context,
1033*ae771770SStanislav Sedov 	     krb5_ccache id,
1034*ae771770SStanislav Sedov 	     krb5_cc_cursor *cursor)
1035*ae771770SStanislav Sedov {
1036*ae771770SStanislav Sedov     struct cred_ctx *ctx = *cursor;
1037*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
1038*ae771770SStanislav Sedov 
1039*ae771770SStanislav Sedov     sqlite3_finalize(ctx->stmt);
1040*ae771770SStanislav Sedov     sqlite3_finalize(ctx->credstmt);
1041*ae771770SStanislav Sedov 
1042*ae771770SStanislav Sedov     exec_stmt(context, s->db, ctx->drop, 0);
1043*ae771770SStanislav Sedov 
1044*ae771770SStanislav Sedov     free(ctx->drop);
1045*ae771770SStanislav Sedov     free(ctx);
1046*ae771770SStanislav Sedov 
1047*ae771770SStanislav Sedov     return 0;
1048*ae771770SStanislav Sedov }
1049*ae771770SStanislav Sedov 
1050*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_remove_cred(krb5_context context,krb5_ccache id,krb5_flags which,krb5_creds * mcreds)1051*ae771770SStanislav Sedov scc_remove_cred(krb5_context context,
1052*ae771770SStanislav Sedov 		 krb5_ccache id,
1053*ae771770SStanislav Sedov 		 krb5_flags which,
1054*ae771770SStanislav Sedov 		 krb5_creds *mcreds)
1055*ae771770SStanislav Sedov {
1056*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
1057*ae771770SStanislav Sedov     krb5_error_code ret;
1058*ae771770SStanislav Sedov     sqlite3_stmt *stmt;
1059*ae771770SStanislav Sedov     sqlite_uint64 credid = 0;
1060*ae771770SStanislav Sedov     const void *data = NULL;
1061*ae771770SStanislav Sedov     size_t len = 0;
1062*ae771770SStanislav Sedov 
1063*ae771770SStanislav Sedov     ret = make_database(context, s);
1064*ae771770SStanislav Sedov     if (ret)
1065*ae771770SStanislav Sedov 	return ret;
1066*ae771770SStanislav Sedov 
1067*ae771770SStanislav Sedov     ret = prepare_stmt(context, s->db, &stmt,
1068*ae771770SStanislav Sedov 		       "SELECT cred,oid FROM credentials "
1069*ae771770SStanislav Sedov 		       "WHERE cid = ?");
1070*ae771770SStanislav Sedov     if (ret)
1071*ae771770SStanislav Sedov 	return ret;
1072*ae771770SStanislav Sedov 
1073*ae771770SStanislav Sedov     sqlite3_bind_int(stmt, 1, s->cid);
1074*ae771770SStanislav Sedov 
1075*ae771770SStanislav Sedov     /* find credential... */
1076*ae771770SStanislav Sedov     while (1) {
1077*ae771770SStanislav Sedov 	krb5_creds creds;
1078*ae771770SStanislav Sedov 
1079*ae771770SStanislav Sedov 	ret = sqlite3_step(stmt);
1080*ae771770SStanislav Sedov 	if (ret == SQLITE_DONE) {
1081*ae771770SStanislav Sedov 	    ret = 0;
1082*ae771770SStanislav Sedov 	    break;
1083*ae771770SStanislav Sedov 	} else if (ret != SQLITE_ROW) {
1084*ae771770SStanislav Sedov 	    ret = KRB5_CC_IO;
1085*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
1086*ae771770SStanislav Sedov 				   N_("scache Database failed: %s", ""),
1087*ae771770SStanislav Sedov 				   sqlite3_errmsg(s->db));
1088*ae771770SStanislav Sedov 	    break;
1089*ae771770SStanislav Sedov 	}
1090*ae771770SStanislav Sedov 
1091*ae771770SStanislav Sedov 	if (sqlite3_column_type(stmt, 0) != SQLITE_BLOB) {
1092*ae771770SStanislav Sedov 	    ret = KRB5_CC_END;
1093*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
1094*ae771770SStanislav Sedov 				   N_("Credential of wrong type "
1095*ae771770SStanislav Sedov 				      "for SCC:%s:%s", ""),
1096*ae771770SStanislav Sedov 				   s->name, s->file);
1097*ae771770SStanislav Sedov 	    break;
1098*ae771770SStanislav Sedov 	}
1099*ae771770SStanislav Sedov 
1100*ae771770SStanislav Sedov 	data = sqlite3_column_blob(stmt, 0);
1101*ae771770SStanislav Sedov 	len = sqlite3_column_bytes(stmt, 0);
1102*ae771770SStanislav Sedov 
1103*ae771770SStanislav Sedov 	ret = decode_creds(context, data, len, &creds);
1104*ae771770SStanislav Sedov 	if (ret)
1105*ae771770SStanislav Sedov 	    break;
1106*ae771770SStanislav Sedov 
1107*ae771770SStanislav Sedov 	ret = krb5_compare_creds(context, which, mcreds, &creds);
1108*ae771770SStanislav Sedov 	krb5_free_cred_contents(context, &creds);
1109*ae771770SStanislav Sedov 	if (ret) {
1110*ae771770SStanislav Sedov 	    credid = sqlite3_column_int64(stmt, 1);
1111*ae771770SStanislav Sedov 	    ret = 0;
1112*ae771770SStanislav Sedov 	    break;
1113*ae771770SStanislav Sedov 	}
1114*ae771770SStanislav Sedov     }
1115*ae771770SStanislav Sedov 
1116*ae771770SStanislav Sedov     sqlite3_finalize(stmt);
1117*ae771770SStanislav Sedov 
1118*ae771770SStanislav Sedov     if (id) {
1119*ae771770SStanislav Sedov 	ret = prepare_stmt(context, s->db, &stmt,
1120*ae771770SStanislav Sedov 			   "DELETE FROM credentials WHERE oid=?");
1121*ae771770SStanislav Sedov 	if (ret)
1122*ae771770SStanislav Sedov 	    return ret;
1123*ae771770SStanislav Sedov 	sqlite3_bind_int(stmt, 1, credid);
1124*ae771770SStanislav Sedov 
1125*ae771770SStanislav Sedov 	do {
1126*ae771770SStanislav Sedov 	    ret = sqlite3_step(stmt);
1127*ae771770SStanislav Sedov 	} while (ret == SQLITE_ROW);
1128*ae771770SStanislav Sedov 	sqlite3_finalize(stmt);
1129*ae771770SStanislav Sedov 	if (ret != SQLITE_DONE) {
1130*ae771770SStanislav Sedov 	    ret = KRB5_CC_IO;
1131*ae771770SStanislav Sedov 	    krb5_set_error_message(context, ret,
1132*ae771770SStanislav Sedov 				   N_("failed to delete scache credental", ""));
1133*ae771770SStanislav Sedov 	} else
1134*ae771770SStanislav Sedov 	    ret = 0;
1135*ae771770SStanislav Sedov     }
1136*ae771770SStanislav Sedov 
1137*ae771770SStanislav Sedov     return ret;
1138*ae771770SStanislav Sedov }
1139*ae771770SStanislav Sedov 
1140*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_set_flags(krb5_context context,krb5_ccache id,krb5_flags flags)1141*ae771770SStanislav Sedov scc_set_flags(krb5_context context,
1142*ae771770SStanislav Sedov 	      krb5_ccache id,
1143*ae771770SStanislav Sedov 	      krb5_flags flags)
1144*ae771770SStanislav Sedov {
1145*ae771770SStanislav Sedov     return 0; /* XXX */
1146*ae771770SStanislav Sedov }
1147*ae771770SStanislav Sedov 
1148*ae771770SStanislav Sedov struct cache_iter {
1149*ae771770SStanislav Sedov     char *drop;
1150*ae771770SStanislav Sedov     sqlite3 *db;
1151*ae771770SStanislav Sedov     sqlite3_stmt *stmt;
1152*ae771770SStanislav Sedov };
1153*ae771770SStanislav Sedov 
1154*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_get_cache_first(krb5_context context,krb5_cc_cursor * cursor)1155*ae771770SStanislav Sedov scc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor)
1156*ae771770SStanislav Sedov {
1157*ae771770SStanislav Sedov     struct cache_iter *ctx;
1158*ae771770SStanislav Sedov     krb5_error_code ret;
1159*ae771770SStanislav Sedov     char *name = NULL, *str = NULL;
1160*ae771770SStanislav Sedov 
1161*ae771770SStanislav Sedov     *cursor = NULL;
1162*ae771770SStanislav Sedov 
1163*ae771770SStanislav Sedov     ctx = calloc(1, sizeof(*ctx));
1164*ae771770SStanislav Sedov     if (ctx == NULL) {
1165*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
1166*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
1167*ae771770SStanislav Sedov 	return ENOMEM;
1168*ae771770SStanislav Sedov     }
1169*ae771770SStanislav Sedov 
1170*ae771770SStanislav Sedov     ret = default_db(context, &ctx->db);
1171*ae771770SStanislav Sedov     if (ctx->db == NULL) {
1172*ae771770SStanislav Sedov 	free(ctx);
1173*ae771770SStanislav Sedov 	return ret;
1174*ae771770SStanislav Sedov     }
1175*ae771770SStanislav Sedov 
1176*ae771770SStanislav Sedov     ret = asprintf(&name, "cacheIteration%pPid%d",
1177*ae771770SStanislav Sedov                    ctx, (int)getpid());
1178*ae771770SStanislav Sedov     if (ret < 0 || name == NULL) {
1179*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
1180*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
1181*ae771770SStanislav Sedov 	sqlite3_close(ctx->db);
1182*ae771770SStanislav Sedov 	free(ctx);
1183*ae771770SStanislav Sedov 	return ENOMEM;
1184*ae771770SStanislav Sedov     }
1185*ae771770SStanislav Sedov 
1186*ae771770SStanislav Sedov     ret = asprintf(&ctx->drop, "DROP TABLE %s", name);
1187*ae771770SStanislav Sedov     if (ret < 0 || ctx->drop == NULL) {
1188*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
1189*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
1190*ae771770SStanislav Sedov 	sqlite3_close(ctx->db);
1191*ae771770SStanislav Sedov 	free(name);
1192*ae771770SStanislav Sedov 	free(ctx);
1193*ae771770SStanislav Sedov 	return ENOMEM;
1194*ae771770SStanislav Sedov     }
1195*ae771770SStanislav Sedov 
1196*ae771770SStanislav Sedov     ret = asprintf(&str, "CREATE TEMPORARY TABLE %s AS SELECT name FROM caches",
1197*ae771770SStanislav Sedov 	     name);
1198*ae771770SStanislav Sedov     if (ret < 0 || str == NULL) {
1199*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
1200*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
1201*ae771770SStanislav Sedov 	sqlite3_close(ctx->db);
1202*ae771770SStanislav Sedov 	free(name);
1203*ae771770SStanislav Sedov 	free(ctx->drop);
1204*ae771770SStanislav Sedov 	free(ctx);
1205*ae771770SStanislav Sedov 	return ENOMEM;
1206*ae771770SStanislav Sedov     }
1207*ae771770SStanislav Sedov 
1208*ae771770SStanislav Sedov     ret = exec_stmt(context, ctx->db, str, KRB5_CC_IO);
1209*ae771770SStanislav Sedov     free(str);
1210*ae771770SStanislav Sedov     str = NULL;
1211*ae771770SStanislav Sedov     if (ret) {
1212*ae771770SStanislav Sedov 	sqlite3_close(ctx->db);
1213*ae771770SStanislav Sedov 	free(name);
1214*ae771770SStanislav Sedov 	free(ctx->drop);
1215*ae771770SStanislav Sedov 	free(ctx);
1216*ae771770SStanislav Sedov 	return ret;
1217*ae771770SStanislav Sedov     }
1218*ae771770SStanislav Sedov 
1219*ae771770SStanislav Sedov     ret = asprintf(&str, "SELECT name FROM %s", name);
1220*ae771770SStanislav Sedov     free(name);
1221*ae771770SStanislav Sedov     if (ret < 0 || str == NULL) {
1222*ae771770SStanislav Sedov 	exec_stmt(context, ctx->db, ctx->drop, 0);
1223*ae771770SStanislav Sedov 	sqlite3_close(ctx->db);
1224*ae771770SStanislav Sedov 	free(name);
1225*ae771770SStanislav Sedov 	free(ctx->drop);
1226*ae771770SStanislav Sedov 	free(ctx);
1227*ae771770SStanislav Sedov 	return ENOMEM;
1228*ae771770SStanislav Sedov     }
1229*ae771770SStanislav Sedov 
1230*ae771770SStanislav Sedov     ret = prepare_stmt(context, ctx->db, &ctx->stmt, str);
1231*ae771770SStanislav Sedov     free(str);
1232*ae771770SStanislav Sedov     if (ret) {
1233*ae771770SStanislav Sedov 	exec_stmt(context, ctx->db, ctx->drop, 0);
1234*ae771770SStanislav Sedov 	sqlite3_close(ctx->db);
1235*ae771770SStanislav Sedov 	free(ctx->drop);
1236*ae771770SStanislav Sedov 	free(ctx);
1237*ae771770SStanislav Sedov 	return ret;
1238*ae771770SStanislav Sedov     }
1239*ae771770SStanislav Sedov 
1240*ae771770SStanislav Sedov     *cursor = ctx;
1241*ae771770SStanislav Sedov 
1242*ae771770SStanislav Sedov     return 0;
1243*ae771770SStanislav Sedov }
1244*ae771770SStanislav Sedov 
1245*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_get_cache_next(krb5_context context,krb5_cc_cursor cursor,krb5_ccache * id)1246*ae771770SStanislav Sedov scc_get_cache_next(krb5_context context,
1247*ae771770SStanislav Sedov 		   krb5_cc_cursor cursor,
1248*ae771770SStanislav Sedov 		   krb5_ccache *id)
1249*ae771770SStanislav Sedov {
1250*ae771770SStanislav Sedov     struct cache_iter *ctx = cursor;
1251*ae771770SStanislav Sedov     krb5_error_code ret;
1252*ae771770SStanislav Sedov     const char *name;
1253*ae771770SStanislav Sedov 
1254*ae771770SStanislav Sedov again:
1255*ae771770SStanislav Sedov     ret = sqlite3_step(ctx->stmt);
1256*ae771770SStanislav Sedov     if (ret == SQLITE_DONE) {
1257*ae771770SStanislav Sedov 	krb5_clear_error_message(context);
1258*ae771770SStanislav Sedov         return KRB5_CC_END;
1259*ae771770SStanislav Sedov     } else if (ret != SQLITE_ROW) {
1260*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
1261*ae771770SStanislav Sedov 			       N_("Database failed: %s", ""),
1262*ae771770SStanislav Sedov 			       sqlite3_errmsg(ctx->db));
1263*ae771770SStanislav Sedov         return KRB5_CC_IO;
1264*ae771770SStanislav Sedov     }
1265*ae771770SStanislav Sedov 
1266*ae771770SStanislav Sedov     if (sqlite3_column_type(ctx->stmt, 0) != SQLITE_TEXT)
1267*ae771770SStanislav Sedov 	goto again;
1268*ae771770SStanislav Sedov 
1269*ae771770SStanislav Sedov     name = (const char *)sqlite3_column_text(ctx->stmt, 0);
1270*ae771770SStanislav Sedov     if (name == NULL)
1271*ae771770SStanislav Sedov 	goto again;
1272*ae771770SStanislav Sedov 
1273*ae771770SStanislav Sedov     ret = _krb5_cc_allocate(context, &krb5_scc_ops, id);
1274*ae771770SStanislav Sedov     if (ret)
1275*ae771770SStanislav Sedov 	return ret;
1276*ae771770SStanislav Sedov 
1277*ae771770SStanislav Sedov     return scc_resolve(context, id, name);
1278*ae771770SStanislav Sedov }
1279*ae771770SStanislav Sedov 
1280*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_end_cache_get(krb5_context context,krb5_cc_cursor cursor)1281*ae771770SStanislav Sedov scc_end_cache_get(krb5_context context, krb5_cc_cursor cursor)
1282*ae771770SStanislav Sedov {
1283*ae771770SStanislav Sedov     struct cache_iter *ctx = cursor;
1284*ae771770SStanislav Sedov 
1285*ae771770SStanislav Sedov     exec_stmt(context, ctx->db, ctx->drop, 0);
1286*ae771770SStanislav Sedov     sqlite3_finalize(ctx->stmt);
1287*ae771770SStanislav Sedov     sqlite3_close(ctx->db);
1288*ae771770SStanislav Sedov     free(ctx->drop);
1289*ae771770SStanislav Sedov     free(ctx);
1290*ae771770SStanislav Sedov     return 0;
1291*ae771770SStanislav Sedov }
1292*ae771770SStanislav Sedov 
1293*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_move(krb5_context context,krb5_ccache from,krb5_ccache to)1294*ae771770SStanislav Sedov scc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
1295*ae771770SStanislav Sedov {
1296*ae771770SStanislav Sedov     krb5_scache *sfrom = SCACHE(from);
1297*ae771770SStanislav Sedov     krb5_scache *sto = SCACHE(to);
1298*ae771770SStanislav Sedov     krb5_error_code ret;
1299*ae771770SStanislav Sedov 
1300*ae771770SStanislav Sedov     if (strcmp(sfrom->file, sto->file) != 0) {
1301*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_BADNAME,
1302*ae771770SStanislav Sedov 			       N_("Can't handle cross database "
1303*ae771770SStanislav Sedov 				  "credential move: %s -> %s", ""),
1304*ae771770SStanislav Sedov 			       sfrom->file, sto->file);
1305*ae771770SStanislav Sedov 	return KRB5_CC_BADNAME;
1306*ae771770SStanislav Sedov     }
1307*ae771770SStanislav Sedov 
1308*ae771770SStanislav Sedov     ret = make_database(context, sfrom);
1309*ae771770SStanislav Sedov     if (ret)
1310*ae771770SStanislav Sedov 	return ret;
1311*ae771770SStanislav Sedov 
1312*ae771770SStanislav Sedov     ret = exec_stmt(context, sfrom->db,
1313*ae771770SStanislav Sedov 		    "BEGIN IMMEDIATE TRANSACTION", KRB5_CC_IO);
1314*ae771770SStanislav Sedov     if (ret) return ret;
1315*ae771770SStanislav Sedov 
1316*ae771770SStanislav Sedov     if (sto->cid != SCACHE_INVALID_CID) {
1317*ae771770SStanislav Sedov 	/* drop old cache entry */
1318*ae771770SStanislav Sedov 
1319*ae771770SStanislav Sedov 	sqlite3_bind_int(sfrom->dcache, 1, sto->cid);
1320*ae771770SStanislav Sedov 	do {
1321*ae771770SStanislav Sedov 	    ret = sqlite3_step(sfrom->dcache);
1322*ae771770SStanislav Sedov 	} while (ret == SQLITE_ROW);
1323*ae771770SStanislav Sedov 	sqlite3_reset(sfrom->dcache);
1324*ae771770SStanislav Sedov 	if (ret != SQLITE_DONE) {
1325*ae771770SStanislav Sedov 	    krb5_set_error_message(context, KRB5_CC_IO,
1326*ae771770SStanislav Sedov 				   N_("Failed to delete old cache: %d", ""),
1327*ae771770SStanislav Sedov 				   (int)ret);
1328*ae771770SStanislav Sedov 	    goto rollback;
1329*ae771770SStanislav Sedov 	}
1330*ae771770SStanislav Sedov     }
1331*ae771770SStanislav Sedov 
1332*ae771770SStanislav Sedov     sqlite3_bind_text(sfrom->ucachen, 1, sto->name, -1, NULL);
1333*ae771770SStanislav Sedov     sqlite3_bind_int(sfrom->ucachen, 2, sfrom->cid);
1334*ae771770SStanislav Sedov 
1335*ae771770SStanislav Sedov     do {
1336*ae771770SStanislav Sedov 	ret = sqlite3_step(sfrom->ucachen);
1337*ae771770SStanislav Sedov     } while (ret == SQLITE_ROW);
1338*ae771770SStanislav Sedov     sqlite3_reset(sfrom->ucachen);
1339*ae771770SStanislav Sedov     if (ret != SQLITE_DONE) {
1340*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
1341*ae771770SStanislav Sedov 			       N_("Failed to update new cache: %d", ""),
1342*ae771770SStanislav Sedov 			       (int)ret);
1343*ae771770SStanislav Sedov 	goto rollback;
1344*ae771770SStanislav Sedov     }
1345*ae771770SStanislav Sedov 
1346*ae771770SStanislav Sedov     sto->cid = sfrom->cid;
1347*ae771770SStanislav Sedov 
1348*ae771770SStanislav Sedov     ret = exec_stmt(context, sfrom->db, "COMMIT", KRB5_CC_IO);
1349*ae771770SStanislav Sedov     if (ret) return ret;
1350*ae771770SStanislav Sedov 
1351*ae771770SStanislav Sedov     scc_free(sfrom);
1352*ae771770SStanislav Sedov 
1353*ae771770SStanislav Sedov     return 0;
1354*ae771770SStanislav Sedov 
1355*ae771770SStanislav Sedov rollback:
1356*ae771770SStanislav Sedov     exec_stmt(context, sfrom->db, "ROLLBACK", 0);
1357*ae771770SStanislav Sedov     scc_free(sfrom);
1358*ae771770SStanislav Sedov 
1359*ae771770SStanislav Sedov     return KRB5_CC_IO;
1360*ae771770SStanislav Sedov }
1361*ae771770SStanislav Sedov 
1362*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_get_default_name(krb5_context context,char ** str)1363*ae771770SStanislav Sedov scc_get_default_name(krb5_context context, char **str)
1364*ae771770SStanislav Sedov {
1365*ae771770SStanislav Sedov     krb5_error_code ret;
1366*ae771770SStanislav Sedov     char *name;
1367*ae771770SStanislav Sedov 
1368*ae771770SStanislav Sedov     *str = NULL;
1369*ae771770SStanislav Sedov 
1370*ae771770SStanislav Sedov     ret = get_def_name(context, &name);
1371*ae771770SStanislav Sedov     if (ret)
1372*ae771770SStanislav Sedov 	return _krb5_expand_default_cc_name(context, KRB5_SCACHE_NAME, str);
1373*ae771770SStanislav Sedov 
1374*ae771770SStanislav Sedov     ret = asprintf(str, "SCC:%s", name);
1375*ae771770SStanislav Sedov     free(name);
1376*ae771770SStanislav Sedov     if (ret < 0 || *str == NULL) {
1377*ae771770SStanislav Sedov 	krb5_set_error_message(context, ENOMEM,
1378*ae771770SStanislav Sedov 			       N_("malloc: out of memory", ""));
1379*ae771770SStanislav Sedov 	return ENOMEM;
1380*ae771770SStanislav Sedov     }
1381*ae771770SStanislav Sedov     return 0;
1382*ae771770SStanislav Sedov }
1383*ae771770SStanislav Sedov 
1384*ae771770SStanislav Sedov static krb5_error_code KRB5_CALLCONV
scc_set_default(krb5_context context,krb5_ccache id)1385*ae771770SStanislav Sedov scc_set_default(krb5_context context, krb5_ccache id)
1386*ae771770SStanislav Sedov {
1387*ae771770SStanislav Sedov     krb5_scache *s = SCACHE(id);
1388*ae771770SStanislav Sedov     krb5_error_code ret;
1389*ae771770SStanislav Sedov 
1390*ae771770SStanislav Sedov     if (s->cid == SCACHE_INVALID_CID) {
1391*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
1392*ae771770SStanislav Sedov 			       N_("Trying to set a invalid cache "
1393*ae771770SStanislav Sedov 				  "as default %s", ""),
1394*ae771770SStanislav Sedov 			       s->name);
1395*ae771770SStanislav Sedov 	return KRB5_CC_IO;
1396*ae771770SStanislav Sedov     }
1397*ae771770SStanislav Sedov 
1398*ae771770SStanislav Sedov     ret = sqlite3_bind_text(s->umaster, 1, s->name, -1, NULL);
1399*ae771770SStanislav Sedov     if (ret) {
1400*ae771770SStanislav Sedov 	sqlite3_reset(s->umaster);
1401*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
1402*ae771770SStanislav Sedov 			       N_("Failed to set name of default cache", ""));
1403*ae771770SStanislav Sedov 	return KRB5_CC_IO;
1404*ae771770SStanislav Sedov     }
1405*ae771770SStanislav Sedov 
1406*ae771770SStanislav Sedov     do {
1407*ae771770SStanislav Sedov 	ret = sqlite3_step(s->umaster);
1408*ae771770SStanislav Sedov     } while (ret == SQLITE_ROW);
1409*ae771770SStanislav Sedov     sqlite3_reset(s->umaster);
1410*ae771770SStanislav Sedov     if (ret != SQLITE_DONE) {
1411*ae771770SStanislav Sedov 	krb5_set_error_message(context, KRB5_CC_IO,
1412*ae771770SStanislav Sedov 			       N_("Failed to update default cache", ""));
1413*ae771770SStanislav Sedov 	return KRB5_CC_IO;
1414*ae771770SStanislav Sedov     }
1415*ae771770SStanislav Sedov 
1416*ae771770SStanislav Sedov     return 0;
1417*ae771770SStanislav Sedov }
1418*ae771770SStanislav Sedov 
1419*ae771770SStanislav Sedov /**
1420*ae771770SStanislav Sedov  * Variable containing the SCC based credential cache implemention.
1421*ae771770SStanislav Sedov  *
1422*ae771770SStanislav Sedov  * @ingroup krb5_ccache
1423*ae771770SStanislav Sedov  */
1424*ae771770SStanislav Sedov 
1425*ae771770SStanislav Sedov KRB5_LIB_VARIABLE const krb5_cc_ops krb5_scc_ops = {
1426*ae771770SStanislav Sedov     KRB5_CC_OPS_VERSION,
1427*ae771770SStanislav Sedov     "SCC",
1428*ae771770SStanislav Sedov     scc_get_name,
1429*ae771770SStanislav Sedov     scc_resolve,
1430*ae771770SStanislav Sedov     scc_gen_new,
1431*ae771770SStanislav Sedov     scc_initialize,
1432*ae771770SStanislav Sedov     scc_destroy,
1433*ae771770SStanislav Sedov     scc_close,
1434*ae771770SStanislav Sedov     scc_store_cred,
1435*ae771770SStanislav Sedov     NULL, /* scc_retrieve */
1436*ae771770SStanislav Sedov     scc_get_principal,
1437*ae771770SStanislav Sedov     scc_get_first,
1438*ae771770SStanislav Sedov     scc_get_next,
1439*ae771770SStanislav Sedov     scc_end_get,
1440*ae771770SStanislav Sedov     scc_remove_cred,
1441*ae771770SStanislav Sedov     scc_set_flags,
1442*ae771770SStanislav Sedov     NULL,
1443*ae771770SStanislav Sedov     scc_get_cache_first,
1444*ae771770SStanislav Sedov     scc_get_cache_next,
1445*ae771770SStanislav Sedov     scc_end_cache_get,
1446*ae771770SStanislav Sedov     scc_move,
1447*ae771770SStanislav Sedov     scc_get_default_name,
1448*ae771770SStanislav Sedov     scc_set_default
1449*ae771770SStanislav Sedov };
1450*ae771770SStanislav Sedov 
1451*ae771770SStanislav Sedov #endif
1452