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