Line data Source code
1 : /*
2 : SSSD
3 :
4 : Kerberos 5 Backend Module -- keytab related utilities
5 :
6 : Authors:
7 : Sumit Bose <sbose@redhat.com>
8 :
9 : Copyright (C) 2014 Red Hat
10 :
11 : This program is free software; you can redistribute it and/or modify
12 : it under the terms of the GNU General Public License as published by
13 : the Free Software Foundation; either version 3 of the License, or
14 : (at your option) any later version.
15 :
16 : This program is distributed in the hope that it will be useful,
17 : but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : GNU General Public License for more details.
20 :
21 : You should have received a copy of the GNU General Public License
22 : along with this program. If not, see <http://www.gnu.org/licenses/>.
23 : */
24 :
25 : #include "util/util.h"
26 : #include "util/sss_krb5.h"
27 : #include "providers/krb5/krb5_common.h"
28 :
29 4 : static krb5_error_code do_keytab_copy(krb5_context kctx, krb5_keytab s_keytab,
30 : krb5_keytab d_keytab)
31 : {
32 : krb5_error_code kerr;
33 : krb5_error_code kt_err;
34 : krb5_kt_cursor cursor;
35 : krb5_keytab_entry entry;
36 :
37 4 : memset(&cursor, 0, sizeof(cursor));
38 4 : kerr = krb5_kt_start_seq_get(kctx, s_keytab, &cursor);
39 4 : if (kerr != 0) {
40 0 : DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab.\n");
41 0 : return kerr;
42 : }
43 :
44 4 : memset(&entry, 0, sizeof(entry));
45 24 : while ((kt_err = krb5_kt_next_entry(kctx, s_keytab, &entry,
46 : &cursor)) == 0) {
47 16 : kerr = krb5_kt_add_entry(kctx, d_keytab, &entry);
48 16 : if (kerr != 0) {
49 0 : DEBUG(SSSDBG_OP_FAILURE, "krb5_kt_add_entry failed.\n");
50 0 : kt_err = krb5_kt_end_seq_get(kctx, s_keytab, &cursor);
51 0 : if (kt_err != 0) {
52 0 : DEBUG(SSSDBG_TRACE_ALL,
53 : "krb5_kt_end_seq_get failed with [%d], ignored.\n",
54 : kt_err);
55 : }
56 0 : return kerr;
57 : }
58 :
59 16 : kerr = sss_krb5_free_keytab_entry_contents(kctx, &entry);
60 16 : if (kerr != 0) {
61 0 : DEBUG(SSSDBG_MINOR_FAILURE, "Failed to free keytab entry.\n");
62 0 : kt_err = krb5_kt_end_seq_get(kctx, s_keytab, &cursor);
63 0 : if (kt_err != 0) {
64 0 : DEBUG(SSSDBG_TRACE_ALL,
65 : "krb5_kt_end_seq_get failed with [%d], ignored.\n",
66 : kt_err);
67 : }
68 0 : return kerr;
69 : }
70 16 : memset(&entry, 0, sizeof(entry));
71 : }
72 :
73 4 : kerr = krb5_kt_end_seq_get(kctx, s_keytab, &cursor);
74 4 : if (kerr != 0) {
75 0 : DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_end_seq_get failed.\n");
76 0 : return kerr;
77 : }
78 :
79 : /* check if we got any errors from krb5_kt_next_entry */
80 4 : if (kt_err != 0 && kt_err != KRB5_KT_END) {
81 0 : DEBUG(SSSDBG_CRIT_FAILURE, "error reading keytab.\n");
82 0 : return kt_err;
83 : }
84 :
85 4 : return 0;
86 : }
87 :
88 2 : krb5_error_code copy_keytab_into_memory(TALLOC_CTX *mem_ctx, krb5_context kctx,
89 : const char *inp_keytab_file,
90 : char **_mem_name,
91 : krb5_keytab *_mem_keytab)
92 : {
93 : krb5_error_code kerr;
94 2 : krb5_keytab keytab = NULL;
95 2 : krb5_keytab mem_keytab = NULL;
96 2 : krb5_keytab tmp_mem_keytab = NULL;
97 : char keytab_name[MAX_KEYTAB_NAME_LEN];
98 : char *sep;
99 2 : char *mem_name = NULL;
100 2 : char *tmp_mem_name = NULL;
101 : const char *keytab_file;
102 : char default_keytab_name[MAX_KEYTAB_NAME_LEN];
103 :
104 2 : keytab_file = inp_keytab_file;
105 2 : if (keytab_file == NULL) {
106 0 : kerr = krb5_kt_default_name(kctx, default_keytab_name,
107 : sizeof(default_keytab_name));
108 0 : if (kerr != 0) {
109 0 : DEBUG(SSSDBG_CRIT_FAILURE, "krb5_kt_default_name failed.\n");
110 0 : return kerr;
111 : }
112 :
113 0 : keytab_file = default_keytab_name;
114 : }
115 :
116 2 : kerr = krb5_kt_resolve(kctx, keytab_file, &keytab);
117 2 : if (kerr != 0) {
118 0 : DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
119 : keytab_file);
120 0 : return kerr;
121 : }
122 :
123 2 : kerr = sss_krb5_kt_have_content(kctx, keytab);
124 2 : if (kerr != 0) {
125 0 : DEBUG(SSSDBG_CRIT_FAILURE, "keytab [%s] has not entries.\n",
126 : keytab_file);
127 0 : goto done;
128 : }
129 :
130 2 : kerr = krb5_kt_get_name(kctx, keytab, keytab_name, sizeof(keytab_name));
131 2 : if (kerr != 0) {
132 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to read name for keytab [%s].\n",
133 : keytab_file);
134 0 : goto done;
135 : }
136 :
137 2 : sep = strchr(keytab_name, ':');
138 2 : if (sep == NULL || sep[1] == '\0') {
139 0 : DEBUG(SSSDBG_CRIT_FAILURE,
140 : "Keytab name [%s] does not have delimiter[:] .\n", keytab_name);
141 0 : kerr = KRB5KRB_ERR_GENERIC;
142 0 : goto done;
143 : }
144 :
145 2 : if (strncmp(keytab_name, "MEMORY:", sizeof("MEMORY:") -1) == 0) {
146 0 : DEBUG(SSSDBG_TRACE_FUNC, "Keytab [%s] is already memory keytab.\n",
147 : keytab_name);
148 0 : *_mem_name = talloc_strdup(mem_ctx, keytab_name);
149 0 : if(*_mem_name == NULL) {
150 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_strdup failed.\n");
151 0 : kerr = KRB5KRB_ERR_GENERIC;
152 0 : goto done;
153 : }
154 0 : kerr = 0;
155 0 : goto done;
156 : }
157 :
158 2 : mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s", sep + 1);
159 2 : if (mem_name == NULL) {
160 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
161 0 : kerr = KRB5KRB_ERR_GENERIC;
162 0 : goto done;
163 : }
164 :
165 2 : tmp_mem_name = talloc_asprintf(mem_ctx, "MEMORY:%s.tmp", sep + 1);
166 2 : if (tmp_mem_name == NULL) {
167 0 : DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
168 0 : kerr = KRB5KRB_ERR_GENERIC;
169 0 : goto done;
170 : }
171 :
172 2 : kerr = krb5_kt_resolve(kctx, mem_name, &mem_keytab);
173 2 : if (kerr != 0) {
174 0 : DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
175 : mem_name);
176 0 : goto done;
177 : }
178 :
179 2 : kerr = krb5_kt_resolve(kctx, tmp_mem_name, &tmp_mem_keytab);
180 2 : if (kerr != 0) {
181 0 : DEBUG(SSSDBG_CRIT_FAILURE, "error resolving keytab [%s].\n",
182 : tmp_mem_name);
183 0 : goto done;
184 : }
185 :
186 2 : kerr = do_keytab_copy(kctx, keytab, tmp_mem_keytab);
187 2 : if (kerr != 0) {
188 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy keytab [%s] into [%s].\n",
189 : keytab_file, tmp_mem_name);
190 0 : goto done;
191 : }
192 :
193 : /* krb5_kt_add_entry() adds new entries into MEMORY keytabs at the
194 : * beginning and not at the end as for FILE keytabs. Since we want to keep
195 : * the processing order we have to copy the MEMORY keytab again to retain
196 : * the order from the FILE keytab. */
197 :
198 2 : kerr = do_keytab_copy(kctx, tmp_mem_keytab, mem_keytab);
199 2 : if (kerr != 0) {
200 0 : DEBUG(SSSDBG_CRIT_FAILURE, "Failed to copy keytab [%s] into [%s].\n",
201 : tmp_mem_name, mem_name);
202 0 : goto done;
203 : }
204 :
205 2 : *_mem_name = mem_name;
206 2 : if (_mem_keytab != NULL) {
207 2 : *_mem_keytab = mem_keytab;
208 : }
209 :
210 2 : kerr = 0;
211 : done:
212 :
213 2 : talloc_free(tmp_mem_name);
214 :
215 2 : if (kerr != 0) {
216 0 : talloc_free(mem_name);
217 : }
218 :
219 2 : if (tmp_mem_keytab != NULL && krb5_kt_close(kctx, tmp_mem_keytab) != 0) {
220 0 : DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n");
221 : }
222 :
223 2 : if (keytab != NULL && krb5_kt_close(kctx, keytab) != 0) {
224 0 : DEBUG(SSSDBG_MINOR_FAILURE, "krb5_kt_close failed.\n");
225 : }
226 :
227 2 : return kerr;
228 : }
|