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 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 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 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 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 116 main(int argc, char **argv) 117 { 118 profile_t profile; 119 errcode_t code; 120 int c; 121 char *realm, *kdcs, *master, *domain, *token, *lasts; 122 char *file, **ret_values = NULL; 123 boolean_t set_change = FALSE; 124 struct profile_string_list values; 125 126 file = NULL; 127 domain = NULL; 128 master = NULL; 129 kdcs = NULL; 130 realm = NULL; 131 (void) setlocale(LC_ALL, ""); 132 133 #if !defined(TEXT_DOMAIN) 134 #define TEXT_DOMAIN "SYS_TEST" 135 #endif /* TEXT_DOMAIN */ 136 137 (void) textdomain(TEXT_DOMAIN); 138 139 /* 140 * kconf -f <file> -r <realm> -k <kdc[,kdc]> -m <master_kdc> 141 * -p <kpasswd_protocol> -d <domain> 142 */ 143 while ((c = getopt(argc, argv, "f:r:k:a:s:p:d:m:")) != -1) { 144 switch (c) { 145 case 'f': 146 file = optarg; 147 break; 148 case 'r': 149 realm = optarg; 150 break; 151 case 'k': 152 kdcs = optarg; 153 break; 154 case 'm': 155 master = optarg; 156 break; 157 case 'p': 158 if (strcmp(optarg, "SET_CHANGE") == 0) 159 set_change = TRUE; 160 break; 161 case 'd': 162 domain = optarg; 163 break; 164 default: 165 usage(); 166 break; 167 } 168 } 169 170 code = __profile_init(file, &profile); 171 if (code != 0) { 172 fprintf(stderr, gettext("Wasn't able to initialize profile\n")); 173 exit(code); 174 } 175 176 if (code = init_list(&values)) { 177 fprintf(stderr, gettext("Can not initialize list %d\n"), code); 178 goto error; 179 } 180 token = strtok_r(kdcs, ",", &lasts); 181 do { 182 if (token != NULL) { 183 code = add_to_list(&values, token); 184 if (code != 0) { 185 fprintf(stderr, gettext("Can not add to list " 186 "%d\n"), code); 187 goto error; 188 } 189 } else { 190 fprintf(stderr, gettext("Couldn't parse kdc list %d\n"), 191 code); 192 goto error; 193 } 194 } while ((token = strtok_r(NULL, ",", &lasts)) != NULL); 195 end_list(&values, &ret_values); 196 197 code = __profile_add_realm(profile, realm, master, ret_values, 198 set_change, TRUE); 199 if (code != 0) { 200 fprintf(stderr, gettext("Wasn't able to add realm " 201 "information\n")); 202 goto error; 203 } 204 205 code = __profile_add_domain_mapping(profile, domain, realm); 206 if (code != 0) { 207 fprintf(stderr, gettext("Wasn't able to add domain mapping\n")); 208 goto error; 209 } 210 211 error: 212 if (ret_values != NULL) 213 profile_free_list(ret_values); 214 215 /* 216 * Release profile, which will subsequently flush new profile to file. 217 * If this fails then at least free profile memory. 218 */ 219 if ((code = __profile_release(profile)) != 0) 220 __profile_abandon(profile); 221 222 return (code); 223 } 224