Merge Samba3 and Samba4 together
[amitay/samba.git] / source4 / heimdal / lib / hx509 / lock.c
1 /*
2  * Copyright (c) 2005 - 2006 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden). 
4  * All rights reserved. 
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met: 
9  *
10  * 1. Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer. 
12  *
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. 
16  *
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. 
20  *
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. 
32  */
33
34 #include "hx_locl.h"
35 RCSID("$Id$");
36
37 /**
38  * @page page_lock Locking and unlocking certificates and encrypted data.
39  *
40  * See the library functions here: @ref hx509_lock
41  */
42
43 struct hx509_lock_data {
44     struct _hx509_password password;
45     hx509_certs certs;
46     hx509_prompter_fct prompt;
47     void *prompt_data;
48 };
49
50 static struct hx509_lock_data empty_lock_data = {
51     { 0, NULL }
52 };
53
54 hx509_lock _hx509_empty_lock = &empty_lock_data;
55
56 /*
57  *
58  */
59
60 int
61 hx509_lock_init(hx509_context context, hx509_lock *lock)
62 {
63     hx509_lock l;
64     int ret;
65
66     *lock = NULL;
67
68     l = calloc(1, sizeof(*l));
69     if (l == NULL)
70         return ENOMEM;
71
72     ret = hx509_certs_init(context, 
73                            "MEMORY:locks-internal", 
74                            0,
75                            NULL,
76                            &l->certs);
77     if (ret) {
78         free(l);
79         return ret;
80     }
81
82     *lock = l;
83
84     return 0;
85 }
86
87 int
88 hx509_lock_add_password(hx509_lock lock, const char *password)
89 {
90     void *d;
91     char *s;
92
93     s = strdup(password);
94     if (s == NULL)
95         return ENOMEM;
96
97     d = realloc(lock->password.val,
98                 (lock->password.len + 1) * sizeof(lock->password.val[0]));
99     if (d == NULL) {
100         free(s);
101         return ENOMEM;
102     }
103     lock->password.val = d;
104     lock->password.val[lock->password.len] = s;
105     lock->password.len++;
106
107     return 0;
108 }
109
110 const struct _hx509_password *
111 _hx509_lock_get_passwords(hx509_lock lock)
112 {
113     return &lock->password;
114 }
115
116 hx509_certs
117 _hx509_lock_unlock_certs(hx509_lock lock)
118 {
119     return lock->certs;
120 }
121
122 void
123 hx509_lock_reset_passwords(hx509_lock lock)
124 {
125     int i;
126     for (i = 0; i < lock->password.len; i++)
127         free(lock->password.val[i]);
128     free(lock->password.val);
129     lock->password.val = NULL;
130     lock->password.len = 0;
131 }
132
133 int
134 hx509_lock_add_cert(hx509_context context, hx509_lock lock, hx509_cert cert)
135 {
136     return hx509_certs_add(context, lock->certs, cert);
137 }
138
139 int
140 hx509_lock_add_certs(hx509_context context, hx509_lock lock, hx509_certs certs)
141 {
142     return hx509_certs_merge(context, lock->certs, certs);
143 }
144
145 void
146 hx509_lock_reset_certs(hx509_context context, hx509_lock lock)
147 {
148     hx509_certs certs = lock->certs;
149     int ret;
150     
151     ret = hx509_certs_init(context, 
152                            "MEMORY:locks-internal",
153                            0,
154                            NULL,
155                            &lock->certs);
156     if (ret == 0)
157         hx509_certs_free(&certs);
158     else
159         lock->certs = certs;
160 }
161
162 int
163 _hx509_lock_find_cert(hx509_lock lock, const hx509_query *q, hx509_cert *c)
164 {
165     *c = NULL;
166     return 0;
167 }
168
169 int
170 hx509_lock_set_prompter(hx509_lock lock, hx509_prompter_fct prompt, void *data)
171 {
172     lock->prompt = prompt;
173     lock->prompt_data = data;
174     return 0;
175 }
176
177 void
178 hx509_lock_reset_promper(hx509_lock lock)
179 {
180     lock->prompt = NULL;
181     lock->prompt_data = NULL;
182 }
183
184 static int 
185 default_prompter(void *data, const hx509_prompt *prompter)
186 {
187     if (hx509_prompt_hidden(prompter->type)) {
188         if(UI_UTIL_read_pw_string(prompter->reply.data,
189                                   prompter->reply.length,
190                                   prompter->prompt,
191                                   0))
192             return 1;
193     } else {
194         char *s = prompter->reply.data;
195
196         fputs (prompter->prompt, stdout);
197         fflush (stdout);
198         if(fgets(prompter->reply.data,
199                  prompter->reply.length,
200                  stdin) == NULL)
201             return 1;
202         s[strcspn(s, "\n")] = '\0';
203     }
204     return 0;
205 }
206
207 int
208 hx509_lock_prompt(hx509_lock lock, hx509_prompt *prompt)
209 {
210     if (lock->prompt == NULL)
211         return HX509_CRYPTO_NO_PROMPTER;
212     return (*lock->prompt)(lock->prompt_data, prompt);
213 }
214
215 void
216 hx509_lock_free(hx509_lock lock)
217 {
218     hx509_certs_free(&lock->certs);
219     hx509_lock_reset_passwords(lock);
220     memset(lock, 0, sizeof(*lock));
221     free(lock);
222 }
223
224 int
225 hx509_prompt_hidden(hx509_prompt_type type)
226 {
227     /* default to hidden if unknown */
228
229     switch (type) {
230     case HX509_PROMPT_TYPE_QUESTION:
231     case HX509_PROMPT_TYPE_INFO:
232         return 0;
233     default:
234         return 1;
235     }
236 }
237
238 int
239 hx509_lock_command_string(hx509_lock lock, const char *string)
240 {
241     if (strncasecmp(string, "PASS:", 5) == 0) {
242         hx509_lock_add_password(lock, string + 5);
243     } else if (strcasecmp(string, "PROMPT") == 0) {
244         hx509_lock_set_prompter(lock, default_prompter, NULL);
245     } else
246         return HX509_UNKNOWN_LOCK_COMMAND;
247     return 0;
248 }