1 /* 2 * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include "eng_int.h" 11 12 /* 13 * When querying a ENGINE-specific control command's 'description', this 14 * string is used if the ENGINE_CMD_DEFN has cmd_desc set to NULL. 15 */ 16 static const char *int_no_description = ""; 17 18 /* 19 * These internal functions handle 'CMD'-related control commands when the 20 * ENGINE in question has asked us to take care of it (ie. the ENGINE did not 21 * set the ENGINE_FLAGS_MANUAL_CMD_CTRL flag. 22 */ 23 24 static int int_ctrl_cmd_is_null(const ENGINE_CMD_DEFN *defn) 25 { 26 if ((defn->cmd_num == 0) || (defn->cmd_name == NULL)) 27 return 1; 28 return 0; 29 } 30 31 static int int_ctrl_cmd_by_name(const ENGINE_CMD_DEFN *defn, const char *s) 32 { 33 int idx = 0; 34 while (!int_ctrl_cmd_is_null(defn) && (strcmp(defn->cmd_name, s) != 0)) { 35 idx++; 36 defn++; 37 } 38 if (int_ctrl_cmd_is_null(defn)) 39 /* The given name wasn't found */ 40 return -1; 41 return idx; 42 } 43 44 static int int_ctrl_cmd_by_num(const ENGINE_CMD_DEFN *defn, unsigned int num) 45 { 46 int idx = 0; 47 /* 48 * NB: It is stipulated that 'cmd_defn' lists are ordered by cmd_num. So 49 * our searches don't need to take any longer than necessary. 50 */ 51 while (!int_ctrl_cmd_is_null(defn) && (defn->cmd_num < num)) { 52 idx++; 53 defn++; 54 } 55 if (defn->cmd_num == num) 56 return idx; 57 /* The given cmd_num wasn't found */ 58 return -1; 59 } 60 61 static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, 62 void (*f) (void)) 63 { 64 int idx; 65 char *s = (char *)p; 66 const ENGINE_CMD_DEFN *cdp; 67 68 /* Take care of the easy one first (eg. it requires no searches) */ 69 if (cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE) { 70 if ((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns)) 71 return 0; 72 return e->cmd_defns->cmd_num; 73 } 74 /* One or two commands require that "p" be a valid string buffer */ 75 if ((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) || 76 (cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) || 77 (cmd == ENGINE_CTRL_GET_DESC_FROM_CMD)) { 78 if (s == NULL) { 79 ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ERR_R_PASSED_NULL_PARAMETER); 80 return -1; 81 } 82 } 83 /* Now handle cmd_name -> cmd_num conversion */ 84 if (cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) { 85 if ((e->cmd_defns == NULL) 86 || ((idx = int_ctrl_cmd_by_name(e->cmd_defns, s)) < 0)) { 87 ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NAME); 88 return -1; 89 } 90 return e->cmd_defns[idx].cmd_num; 91 } 92 /* 93 * For the rest of the commands, the 'long' argument must specify a valid 94 * command number - so we need to conduct a search. 95 */ 96 if ((e->cmd_defns == NULL) 97 || ((idx = int_ctrl_cmd_by_num(e->cmd_defns, (unsigned int)i)) < 0)) { 98 ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INVALID_CMD_NUMBER); 99 return -1; 100 } 101 /* Now the logic splits depending on command type */ 102 cdp = &e->cmd_defns[idx]; 103 switch (cmd) { 104 case ENGINE_CTRL_GET_NEXT_CMD_TYPE: 105 cdp++; 106 return int_ctrl_cmd_is_null(cdp) ? 0 : cdp->cmd_num; 107 case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD: 108 return strlen(cdp->cmd_name); 109 case ENGINE_CTRL_GET_NAME_FROM_CMD: 110 return strlen(strcpy(s, cdp->cmd_name)); 111 case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD: 112 return strlen(cdp->cmd_desc == NULL ? int_no_description 113 : cdp->cmd_desc); 114 case ENGINE_CTRL_GET_DESC_FROM_CMD: 115 return strlen(strcpy(s, cdp->cmd_desc == NULL ? int_no_description 116 : cdp->cmd_desc)); 117 case ENGINE_CTRL_GET_CMD_FLAGS: 118 return cdp->cmd_flags; 119 } 120 /* Shouldn't really be here ... */ 121 ENGINEerr(ENGINE_F_INT_CTRL_HELPER, ENGINE_R_INTERNAL_LIST_ERROR); 122 return -1; 123 } 124 125 int ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 126 { 127 int ctrl_exists, ref_exists; 128 if (e == NULL) { 129 ENGINEerr(ENGINE_F_ENGINE_CTRL, ERR_R_PASSED_NULL_PARAMETER); 130 return 0; 131 } 132 CRYPTO_THREAD_write_lock(global_engine_lock); 133 ref_exists = ((e->struct_ref > 0) ? 1 : 0); 134 CRYPTO_THREAD_unlock(global_engine_lock); 135 ctrl_exists = ((e->ctrl == NULL) ? 0 : 1); 136 if (!ref_exists) { 137 ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_REFERENCE); 138 return 0; 139 } 140 /* 141 * Intercept any "root-level" commands before trying to hand them on to 142 * ctrl() handlers. 143 */ 144 switch (cmd) { 145 case ENGINE_CTRL_HAS_CTRL_FUNCTION: 146 return ctrl_exists; 147 case ENGINE_CTRL_GET_FIRST_CMD_TYPE: 148 case ENGINE_CTRL_GET_NEXT_CMD_TYPE: 149 case ENGINE_CTRL_GET_CMD_FROM_NAME: 150 case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD: 151 case ENGINE_CTRL_GET_NAME_FROM_CMD: 152 case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD: 153 case ENGINE_CTRL_GET_DESC_FROM_CMD: 154 case ENGINE_CTRL_GET_CMD_FLAGS: 155 if (ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL)) 156 return int_ctrl_helper(e, cmd, i, p, f); 157 if (!ctrl_exists) { 158 ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION); 159 /* 160 * For these cmd-related functions, failure is indicated by a -1 161 * return value (because 0 is used as a valid return in some 162 * places). 163 */ 164 return -1; 165 } 166 default: 167 break; 168 } 169 /* Anything else requires a ctrl() handler to exist. */ 170 if (!ctrl_exists) { 171 ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_NO_CONTROL_FUNCTION); 172 return 0; 173 } 174 return e->ctrl(e, cmd, i, p, f); 175 } 176 177 int ENGINE_cmd_is_executable(ENGINE *e, int cmd) 178 { 179 int flags; 180 if ((flags = 181 ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd, NULL, NULL)) < 0) { 182 ENGINEerr(ENGINE_F_ENGINE_CMD_IS_EXECUTABLE, 183 ENGINE_R_INVALID_CMD_NUMBER); 184 return 0; 185 } 186 if (!(flags & ENGINE_CMD_FLAG_NO_INPUT) && 187 !(flags & ENGINE_CMD_FLAG_NUMERIC) && 188 !(flags & ENGINE_CMD_FLAG_STRING)) 189 return 0; 190 return 1; 191 } 192 193 int ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, 194 long i, void *p, void (*f) (void), int cmd_optional) 195 { 196 int num; 197 198 if (e == NULL || cmd_name == NULL) { 199 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ERR_R_PASSED_NULL_PARAMETER); 200 return 0; 201 } 202 if (e->ctrl == NULL 203 || (num = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME, 204 0, (void *)cmd_name, NULL)) <= 0) { 205 /* 206 * If the command didn't *have* to be supported, we fake success. 207 * This allows certain settings to be specified for multiple ENGINEs 208 * and only require a change of ENGINE id (without having to 209 * selectively apply settings). Eg. changing from a hardware device 210 * back to the regular software ENGINE without editing the config 211 * file, etc. 212 */ 213 if (cmd_optional) { 214 ERR_clear_error(); 215 return 1; 216 } 217 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD, ENGINE_R_INVALID_CMD_NAME); 218 return 0; 219 } 220 /* 221 * Force the result of the control command to 0 or 1, for the reasons 222 * mentioned before. 223 */ 224 if (ENGINE_ctrl(e, num, i, p, f) > 0) 225 return 1; 226 return 0; 227 } 228 229 int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg, 230 int cmd_optional) 231 { 232 int num, flags; 233 long l; 234 char *ptr; 235 236 if (e == NULL || cmd_name == NULL) { 237 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ERR_R_PASSED_NULL_PARAMETER); 238 return 0; 239 } 240 if (e->ctrl == NULL 241 || (num = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FROM_NAME, 242 0, (void *)cmd_name, NULL)) <= 0) { 243 /* 244 * If the command didn't *have* to be supported, we fake success. 245 * This allows certain settings to be specified for multiple ENGINEs 246 * and only require a change of ENGINE id (without having to 247 * selectively apply settings). Eg. changing from a hardware device 248 * back to the regular software ENGINE without editing the config 249 * file, etc. 250 */ 251 if (cmd_optional) { 252 ERR_clear_error(); 253 return 1; 254 } 255 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, ENGINE_R_INVALID_CMD_NAME); 256 return 0; 257 } 258 if (!ENGINE_cmd_is_executable(e, num)) { 259 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, 260 ENGINE_R_CMD_NOT_EXECUTABLE); 261 return 0; 262 } 263 264 flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL); 265 if (flags < 0) { 266 /* 267 * Shouldn't happen, given that ENGINE_cmd_is_executable() returned 268 * success. 269 */ 270 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, 271 ENGINE_R_INTERNAL_LIST_ERROR); 272 return 0; 273 } 274 /* 275 * If the command takes no input, there must be no input. And vice versa. 276 */ 277 if (flags & ENGINE_CMD_FLAG_NO_INPUT) { 278 if (arg != NULL) { 279 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, 280 ENGINE_R_COMMAND_TAKES_NO_INPUT); 281 return 0; 282 } 283 /* 284 * We deliberately force the result of ENGINE_ctrl() to 0 or 1 rather 285 * than returning it as "return data". This is to ensure usage of 286 * these commands is consistent across applications and that certain 287 * applications don't understand it one way, and others another. 288 */ 289 if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0) 290 return 1; 291 return 0; 292 } 293 /* So, we require input */ 294 if (arg == NULL) { 295 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, 296 ENGINE_R_COMMAND_TAKES_INPUT); 297 return 0; 298 } 299 /* If it takes string input, that's easy */ 300 if (flags & ENGINE_CMD_FLAG_STRING) { 301 /* Same explanation as above */ 302 if (ENGINE_ctrl(e, num, 0, (void *)arg, NULL) > 0) 303 return 1; 304 return 0; 305 } 306 /* 307 * If it doesn't take numeric either, then it is unsupported for use in a 308 * config-setting situation, which is what this function is for. This 309 * should never happen though, because ENGINE_cmd_is_executable() was 310 * used. 311 */ 312 if (!(flags & ENGINE_CMD_FLAG_NUMERIC)) { 313 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, 314 ENGINE_R_INTERNAL_LIST_ERROR); 315 return 0; 316 } 317 l = strtol(arg, &ptr, 10); 318 if ((arg == ptr) || (*ptr != '\0')) { 319 ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING, 320 ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER); 321 return 0; 322 } 323 /* 324 * Force the result of the control command to 0 or 1, for the reasons 325 * mentioned before. 326 */ 327 if (ENGINE_ctrl(e, num, l, NULL, NULL) > 0) 328 return 1; 329 return 0; 330 } 331