1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* lib/krb5/krb/response_items.c - Response items */ 3 /* 4 * Copyright 2012 Red Hat, Inc. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of Red Hat not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original Red Hat software. 22 * Red Hat makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include "k5-int.h" 28 #include "int-proto.h" 29 30 struct k5_response_items_st { 31 size_t count; 32 char **questions; 33 char **challenges; 34 char **answers; 35 }; 36 37 krb5_error_code 38 k5_response_items_new(k5_response_items **ri_out) 39 { 40 *ri_out = calloc(1, sizeof(**ri_out)); 41 return (*ri_out == NULL) ? ENOMEM : 0; 42 } 43 44 void 45 k5_response_items_free(k5_response_items *ri) 46 { 47 k5_response_items_reset(ri); 48 free(ri); 49 } 50 51 void 52 k5_response_items_reset(k5_response_items *ri) 53 { 54 size_t i; 55 56 if (ri == NULL) 57 return; 58 59 for (i = 0; i < ri->count; i++) 60 free(ri->questions[i]); 61 free(ri->questions); 62 ri->questions = NULL; 63 64 for (i = 0; i < ri->count; i++) 65 zapfreestr(ri->challenges[i]); 66 free(ri->challenges); 67 ri->challenges = NULL; 68 69 for (i = 0; i < ri->count; i++) 70 zapfreestr(ri->answers[i]); 71 free(ri->answers); 72 ri->answers = NULL; 73 74 ri->count = 0; 75 } 76 77 krb5_boolean 78 k5_response_items_empty(const k5_response_items *ri) 79 { 80 return ri == NULL ? TRUE : ri->count == 0; 81 } 82 83 const char * const * 84 k5_response_items_list_questions(const k5_response_items *ri) 85 { 86 if (ri == NULL) 87 return NULL; 88 return (const char * const *)ri->questions; 89 } 90 91 static ssize_t 92 find_question(const k5_response_items *ri, const char *question) 93 { 94 size_t i; 95 96 if (ri == NULL) 97 return -1; 98 99 for (i = 0; i < ri->count; i++) { 100 if (strcmp(ri->questions[i], question) == 0) 101 return i; 102 } 103 104 return -1; 105 } 106 107 static krb5_error_code 108 push_question(k5_response_items *ri, const char *question, 109 const char *challenge) 110 { 111 char **tmp; 112 size_t size; 113 114 if (ri == NULL) 115 return EINVAL; 116 117 size = sizeof(char *) * (ri->count + 2); 118 tmp = realloc(ri->questions, size); 119 if (tmp == NULL) 120 return ENOMEM; 121 ri->questions = tmp; 122 ri->questions[ri->count] = NULL; 123 ri->questions[ri->count + 1] = NULL; 124 125 tmp = realloc(ri->challenges, size); 126 if (tmp == NULL) 127 return ENOMEM; 128 ri->challenges = tmp; 129 ri->challenges[ri->count] = NULL; 130 ri->challenges[ri->count + 1] = NULL; 131 132 tmp = realloc(ri->answers, size); 133 if (tmp == NULL) 134 return ENOMEM; 135 ri->answers = tmp; 136 ri->answers[ri->count] = NULL; 137 ri->answers[ri->count + 1] = NULL; 138 139 ri->questions[ri->count] = strdup(question); 140 if (ri->questions[ri->count] == NULL) 141 return ENOMEM; 142 143 if (challenge != NULL) { 144 ri->challenges[ri->count] = strdup(challenge); 145 if (ri->challenges[ri->count] == NULL) { 146 free(ri->questions[ri->count]); 147 ri->questions[ri->count] = NULL; 148 return ENOMEM; 149 } 150 } 151 152 ri->count++; 153 return 0; 154 } 155 156 krb5_error_code 157 k5_response_items_ask_question(k5_response_items *ri, const char *question, 158 const char *challenge) 159 { 160 ssize_t i; 161 char *tmp = NULL; 162 163 i = find_question(ri, question); 164 if (i < 0) 165 return push_question(ri, question, challenge); 166 167 if (challenge != NULL) { 168 tmp = strdup(challenge); 169 if (tmp == NULL) 170 return ENOMEM; 171 } 172 173 zapfreestr(ri->challenges[i]); 174 ri->challenges[i] = tmp; 175 return 0; 176 } 177 178 const char * 179 k5_response_items_get_challenge(const k5_response_items *ri, 180 const char *question) 181 { 182 ssize_t i; 183 184 i = find_question(ri, question); 185 if (i < 0) 186 return NULL; 187 188 return ri->challenges[i]; 189 } 190 191 krb5_error_code 192 k5_response_items_set_answer(k5_response_items *ri, const char *question, 193 const char *answer) 194 { 195 char *tmp = NULL; 196 ssize_t i; 197 198 i = find_question(ri, question); 199 if (i < 0) 200 return EINVAL; 201 202 if (answer != NULL) { 203 tmp = strdup(answer); 204 if (tmp == NULL) 205 return ENOMEM; 206 } 207 208 zapfreestr(ri->answers[i]); 209 ri->answers[i] = tmp; 210 return 0; 211 } 212 213 const char * 214 k5_response_items_get_answer(const k5_response_items *ri, 215 const char *question) 216 { 217 ssize_t i; 218 219 i = find_question(ri, question); 220 if (i < 0) 221 return NULL; 222 223 return ri->answers[i]; 224 } 225