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 (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