1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <strings.h>
29 #include <locale.h>
30 #include <errno.h>
31 #include <krb5.h>
32 #include <profile.h>
33 #include <com_err.h>
34
35 struct profile_string_list {
36 char **list;
37 int num;
38 int max;
39 };
40
41 /*
42 * From prof_get.c as the following four functions are private in mech_krb5.
43 */
44 /*
45 * Initialize the string list abstraction.
46 */
47 static errcode_t
init_list(struct profile_string_list * list)48 init_list(struct profile_string_list *list)
49 {
50 list->num = 0;
51 list->max = 10;
52 list->list = malloc(list->max * sizeof (char *));
53 if (list->list == NULL)
54 return (ENOMEM);
55 list->list[0] = NULL;
56 return (0);
57 }
58
59 /*
60 * If re_list is non-NULL then pass the list header to the caller else free
61 * the previously allocated list.
62 */
63 static void
end_list(struct profile_string_list * list,char *** ret_list)64 end_list(struct profile_string_list *list, char ***ret_list)
65 {
66
67 if (list == NULL)
68 return;
69
70 if (ret_list) {
71 *ret_list = list->list;
72 return;
73 } else
74 profile_free_list(list->list);
75 list->num = list->max = 0;
76 list->list = NULL;
77 }
78
79 /*
80 * Add a string to the list.
81 */
82 static errcode_t
add_to_list(struct profile_string_list * list,const char * str)83 add_to_list(struct profile_string_list *list, const char *str)
84 {
85 char *newstr, **newlist;
86 int newmax;
87
88 if (list->num + 1 >= list->max) {
89 newmax = list->max + 10;
90 newlist = realloc(list->list, newmax * sizeof (char *));
91 if (newlist == NULL)
92 return (ENOMEM);
93 list->max = newmax;
94 list->list = newlist;
95 }
96 newstr = strdup(str);
97 if (newstr == NULL)
98 return (ENOMEM);
99
100 list->list[list->num++] = newstr;
101 list->list[list->num] = NULL;
102 return (0);
103 }
104
105 static void
usage()106 usage()
107 {
108 (void) fprintf(stderr, gettext("kconf -f <file> -r <realm> "
109 "-k <kdc[,kdc]> -m <master_kdc>\n -p <kpasswd_protocol> "
110 "-d <domain>\n"));
111
112 exit(1);
113 }
114
115 int
main(int argc,char ** argv)116 main(int argc, char **argv)
117 {
118 profile_t profile;
119 errcode_t code;
120 char c, *realm, *kdcs, *master, *domain, *token, *lasts;
121 char *file, **ret_values = NULL;
122 boolean_t set_change = FALSE;
123 struct profile_string_list values;
124
125 (void) setlocale(LC_ALL, "");
126
127 #if !defined(TEXT_DOMAIN)
128 #define TEXT_DOMAIN "SYS_TEST"
129 #endif /* TEXT_DOMAIN */
130
131 (void) textdomain(TEXT_DOMAIN);
132
133 /*
134 * kconf -f <file> -r <realm> -k <kdc[,kdc]> -m <master_kdc>
135 * -p <kpasswd_protocol> -d <domain>
136 */
137 while ((c = getopt(argc, argv, "f:r:k:a:s:p:d:m:")) != -1) {
138 switch (c) {
139 case 'f':
140 file = optarg;
141 break;
142 case 'r':
143 realm = optarg;
144 break;
145 case 'k':
146 kdcs = optarg;
147 break;
148 case 'm':
149 master = optarg;
150 break;
151 case 'p':
152 if (strcmp(optarg, "SET_CHANGE") == 0)
153 set_change = TRUE;
154 break;
155 case 'd':
156 domain = optarg;
157 break;
158 default:
159 usage();
160 break;
161 }
162 }
163
164 code = __profile_init(file, &profile);
165 if (code != 0) {
166 fprintf(stderr, gettext("Wasn't able to initialize profile\n"));
167 exit(code);
168 }
169
170 if (code = init_list(&values)) {
171 fprintf(stderr, gettext("Can not initialize list %d\n"), code);
172 goto error;
173 }
174 token = strtok_r(kdcs, ",", &lasts);
175 do {
176 if (token != NULL) {
177 code = add_to_list(&values, token);
178 if (code != 0) {
179 fprintf(stderr, gettext("Can not add to list "
180 "%d\n"), code);
181 goto error;
182 }
183 } else {
184 fprintf(stderr, gettext("Couldn't parse kdc list %d\n"),
185 code);
186 goto error;
187 }
188 } while ((token = strtok_r(NULL, ",", &lasts)) != NULL);
189 end_list(&values, &ret_values);
190
191 code = __profile_add_realm(profile, realm, master, ret_values,
192 set_change, TRUE);
193 if (code != 0) {
194 fprintf(stderr, gettext("Wasn't able to add realm "
195 "information\n"));
196 goto error;
197 }
198
199 code = __profile_add_domain_mapping(profile, domain, realm);
200 if (code != 0) {
201 fprintf(stderr, gettext("Wasn't able to add domain mapping\n"));
202 goto error;
203 }
204
205 error:
206 if (ret_values != NULL)
207 profile_free_list(ret_values);
208
209 /*
210 * Release profile, which will subsequently flush new profile to file.
211 * If this fails then at least free profile memory.
212 */
213 if ((code = __profile_release(profile)) != NULL)
214 __profile_abandon(profile);
215
216 return (code);
217 }
218