1 /* 2 * Copyright (C) 2023 Yubico AB - See COPYING 3 */ 4 5 #include <stdint.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <limits.h> 9 10 #include "util.h" 11 12 static int buf_write(uint8_t **dst, size_t *size, const void *src, size_t n) { 13 if (*size < n) { 14 return -1; 15 } 16 17 memcpy(*dst, src, n); 18 *dst += n; 19 *size -= n; 20 21 return 0; 22 } 23 24 static int buf_write_byte(uint8_t **dst, size_t *size, uint8_t c) { 25 return buf_write(dst, size, &c, sizeof(c)); 26 } 27 28 static const char *lookup(char var, const char *user) { 29 switch (var) { 30 case 'u': 31 return user; 32 case '%': 33 return "%"; 34 default: 35 // Capture all unknown variables (incl. null byte). 36 return NULL; 37 } 38 } 39 40 char *expand_variables(const char *str, const char *user) { 41 uint8_t *tail, *head; 42 size_t size = PATH_MAX; 43 int ok = -1; 44 45 if (str == NULL || (tail = head = malloc(size)) == NULL) { 46 return NULL; 47 } 48 49 for (; *str != '\0'; str++) { 50 if (*str == '%') { 51 str++; 52 const char *value = lookup(*str, user); 53 if (value == NULL || *value == '\0' || 54 buf_write(&head, &size, value, strlen(value)) != 0) { 55 goto fail; 56 } 57 } else if (buf_write_byte(&head, &size, (uint8_t)*str) != 0) { 58 goto fail; 59 } 60 } 61 62 ok = buf_write_byte(&head, &size, '\0'); 63 64 fail: 65 if (ok != 0) { 66 free(tail); 67 return NULL; 68 } 69 return (char *) tail; 70 } 71