KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_expand_path_tokens(krb5_context context, const char *path_in, char **ppath_out) { char *tok_begin, *tok_end, *append; const char *path_left; size_t len = 0; if (path_in == NULL || *path_in == '\0') { *ppath_out = strdup(""); return 0; } *ppath_out = NULL; for (path_left = path_in; path_left && *path_left; ) { tok_begin = strstr(path_left, "%{"); if (tok_begin && tok_begin != path_left) { append = malloc((tok_begin - path_left) + 1); if (append) { memcpy(append, path_left, tok_begin - path_left); append[tok_begin - path_left] = '\0'; } path_left = tok_begin; } else if (tok_begin) { tok_end = strchr(tok_begin, '}'); if (tok_end == NULL) { if (*ppath_out) free(*ppath_out); *ppath_out = NULL; if (context) krb5_set_error_message(context, EINVAL, "variable missing }"); return EINVAL; } if (_expand_token(context, tok_begin, tok_end, &append)) { if (*ppath_out) free(*ppath_out); *ppath_out = NULL; return EINVAL; } path_left = tok_end + 1; } else { append = strdup(path_left); path_left = NULL; } if (append == NULL) { if (*ppath_out) free(*ppath_out); *ppath_out = NULL; if (context) krb5_set_error_message(context, ENOMEM, "malloc - out of memory"); return ENOMEM; } { size_t append_len = strlen(append); char * new_str = realloc(*ppath_out, len + append_len + 1); if (new_str == NULL) { free(append); if (*ppath_out) free(*ppath_out); *ppath_out = NULL; if (context) krb5_set_error_message(context, ENOMEM, "malloc - out of memory"); return ENOMEM; } *ppath_out = new_str; memcpy(*ppath_out + len, append, append_len + 1); len = len + append_len; free(append); } } #ifdef _WIN32 /* Also deal with slashes */ if (*ppath_out) { char * c; for (c = *ppath_out; *c; c++) if (*c == '/') *c = '\\'; } #endif return 0; }
/** * Internal function to expand tokens in paths. * * Inputs: * * @context A krb5_context * @path_in The path to expand tokens from * @token Variable number of pairs of strings, the first of each * being a token (e.g., "luser") and the second a string to * replace it with. The list is terminated by a NULL. * * Outputs: * * @ppath_out Path with expanded tokens (caller must free() this) */ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL _krb5_expand_path_tokensv(krb5_context context, const char *path_in, char **ppath_out, ...) { char *tok_begin, *tok_end, *append; char **extra_tokens = NULL; const char *path_left; const char *s; size_t nextra_tokens = 0; size_t len = 0; va_list ap; if (path_in == NULL || *path_in == '\0') { *ppath_out = strdup(""); return 0; } *ppath_out = NULL; va_start(ap, ppath_out); while ((s = va_arg(ap, const char *))) { nextra_tokens++; s = va_arg(ap, const char *); } va_end(ap); /* Get extra tokens */ if (nextra_tokens) { size_t i; extra_tokens = calloc(nextra_tokens + 2, sizeof (*extra_tokens)); if (extra_tokens == NULL) return krb5_enomem(context); va_start(ap, ppath_out); for (i = 0; i < nextra_tokens; i++) { s = va_arg(ap, const char *); if (s == NULL) break; extra_tokens[i] = strdup(s); if (extra_tokens[i++] == NULL) { free_extra_tokens(extra_tokens); return krb5_enomem(context); } s = va_arg(ap, const char *); if (s == NULL) break; extra_tokens[i] = strdup(s); if (extra_tokens[i] == NULL) { free_extra_tokens(extra_tokens); return krb5_enomem(context); } } va_end(ap); } for (path_left = path_in; path_left && *path_left; ) { tok_begin = strstr(path_left, "%{"); if (tok_begin && tok_begin != path_left) { append = malloc((tok_begin - path_left) + 1); if (append) { memcpy(append, path_left, tok_begin - path_left); append[tok_begin - path_left] = '\0'; } path_left = tok_begin; } else if (tok_begin) { tok_end = strchr(tok_begin, '}'); if (tok_end == NULL) { free_extra_tokens(extra_tokens); if (*ppath_out) free(*ppath_out); *ppath_out = NULL; if (context) krb5_set_error_message(context, EINVAL, "variable missing }"); return EINVAL; } if (_expand_token(context, tok_begin, tok_end, extra_tokens, &append)) { free_extra_tokens(extra_tokens); if (*ppath_out) free(*ppath_out); *ppath_out = NULL; return EINVAL; } path_left = tok_end + 1; } else { append = strdup(path_left); path_left = NULL; } if (append == NULL) { free_extra_tokens(extra_tokens); if (*ppath_out) free(*ppath_out); *ppath_out = NULL; return krb5_enomem(context); } { size_t append_len = strlen(append); char * new_str = realloc(*ppath_out, len + append_len + 1); if (new_str == NULL) { free_extra_tokens(extra_tokens); free(append); if (*ppath_out) free(*ppath_out); *ppath_out = NULL; return krb5_enomem(context); } *ppath_out = new_str; memcpy(*ppath_out + len, append, append_len + 1); len = len + append_len; free(append); } } #ifdef _WIN32 /* Also deal with slashes */ if (*ppath_out) { char * c; for (c = *ppath_out; *c; c++) if (*c == '/') *c = '\\'; } #endif free_extra_tokens(extra_tokens); return 0; }