cscg24-guacamole

CSCG 2024 Challenge 'Guacamole Mashup'
git clone https://git.sinitax.com/sinitax/cscg24-guacamole
Log | Files | Refs | sfeed.txt

url.c (5633B)


      1/*
      2 * Licensed to the Apache Software Foundation (ASF) under one
      3 * or more contributor license agreements.  See the NOTICE file
      4 * distributed with this work for additional information
      5 * regarding copyright ownership.  The ASF licenses this file
      6 * to you under the Apache License, Version 2.0 (the
      7 * "License"); you may not use this file except in compliance
      8 * with the License.  You may obtain a copy of the License at
      9 *
     10 *   http://www.apache.org/licenses/LICENSE-2.0
     11 *
     12 * Unless required by applicable law or agreed to in writing,
     13 * software distributed under the License is distributed on an
     14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     15 * KIND, either express or implied.  See the License for the
     16 * specific language governing permissions and limitations
     17 * under the License.
     18 */
     19
     20#include "url.h"
     21
     22#include <stdio.h>
     23#include <stdlib.h>
     24#include <string.h>
     25
     26/**
     27 * Returns whether the given character is a character that need not be
     28 * escaped when included as part of a component of a URL.
     29 *
     30 * @param c
     31 *     The character to test.
     32 *
     33 * @return
     34 *     Zero if the character does not need to be escaped when included as
     35 *     part of a component of a URL, non-zero otherwise.
     36 */
     37static int guac_kubernetes_is_url_safe(char c) {
     38    return (c >= 'A' && c <= 'Z')
     39        || (c >= 'a' && c <= 'z')
     40        || (c >= '0' && c <= '9')
     41        || strchr("-_.!~*'()", c) != NULL;
     42}
     43
     44int guac_kubernetes_escape_url_component(char* output, int length,
     45        const char* str) {
     46
     47    char* current = output;
     48    while (*str != '\0') {
     49
     50        char c = *str;
     51
     52        /* Store alphanumeric characters verbatim */
     53        if (guac_kubernetes_is_url_safe(c)) {
     54
     55            /* Verify space exists for single character */
     56            if (length < 1)
     57                return 1;
     58
     59            *(current++) = c;
     60            length--;
     61
     62        }
     63
     64        /* Escape EVERYTHING else as hex */
     65        else {
     66
     67            /* Verify space exists for hex-encoded character */
     68            if (length < 4)
     69                return 1;
     70
     71            snprintf(current, 4, "%%%02X", (int) c);
     72
     73            current += 3;
     74            length -= 3;
     75        }
     76
     77        /* Next character */
     78        str++;
     79
     80    }
     81
     82    /* Verify space exists for null terminator */
     83    if (length < 1)
     84        return 1;
     85
     86    /* Append null terminator */
     87    *current = '\0';
     88    return 0;
     89
     90}
     91
     92int guac_kubernetes_append_endpoint_param(char* buffer, int length, 
     93        const char* param_name, const char* param_value) {
     94
     95    char escaped_param_value[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH];
     96
     97    /* Escape value */
     98    if (guac_kubernetes_escape_url_component(escaped_param_value,
     99                    sizeof(escaped_param_value), param_value))
    100            return 1;
    101    
    102    char* str = buffer;
    103
    104    int str_len = 0;
    105    int qmark = 0;
    106
    107    while (*str != '\0') {
    108
    109        /* Look for a question mark */
    110        if (*str=='?') qmark = 1;
    111
    112        /* Compute the buffer string length */
    113        str_len++;
    114
    115        /* Verify the buffer null terminated */
    116        if (str_len >= length) return 1;
    117
    118        /* Next character */
    119        str++;
    120    }
    121
    122    /* Determine the parameter delimiter */
    123    char delimiter = '?';
    124    if (qmark) delimiter = '&';
    125
    126    /* Advance to end of buffer, where the new parameter and delimiter need to
    127     * be appended */
    128    buffer += str_len;
    129    length -= str_len;
    130
    131    /* Write the parameter and delimiter to the buffer */
    132    int written = snprintf(buffer, length, "%c%s=%s", delimiter,
    133            param_name, escaped_param_value);
    134
    135    /* The parameter was successfully added if it was written to the given
    136     * buffer without truncation */
    137    return (written < 0 || written >= length);
    138}
    139
    140int guac_kubernetes_endpoint_uri(char* buffer, int length,
    141        const char* kubernetes_namespace, const char* kubernetes_pod,
    142        const char* kubernetes_container, const char* exec_command) {
    143
    144    char escaped_namespace[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH];
    145    char escaped_pod[GUAC_KUBERNETES_MAX_ENDPOINT_LENGTH];
    146
    147    /* Escape Kubernetes namespace */
    148    if (guac_kubernetes_escape_url_component(escaped_namespace,
    149                sizeof(escaped_namespace), kubernetes_namespace))
    150        return 1;
    151
    152    /* Escape name of Kubernetes pod */
    153    if (guac_kubernetes_escape_url_component(escaped_pod,
    154                sizeof(escaped_pod), kubernetes_pod))
    155        return 1;
    156
    157    /* Determine the call type */
    158    char* call = "attach";
    159    if (exec_command != NULL)
    160        call = "exec";
    161
    162    int written;
    163
    164    /* Generate the endpoint path and write to the buffer */
    165    written = snprintf(buffer, length,
    166        "/api/v1/namespaces/%s/pods/%s/%s", escaped_namespace, escaped_pod, call);
    167
    168    /* Operation successful if the endpoint path was written to the given
    169     * buffer without truncation */
    170    if (written < 0 || written >= length)
    171        return 1;
    172
    173    /* Append exec command parameter */
    174    if (exec_command != NULL) {
    175        if (guac_kubernetes_append_endpoint_param(buffer,
    176                    length, "command", exec_command))
    177            return 1;
    178    }
    179
    180    /* Append kubernetes container parameter */
    181    if (kubernetes_container != NULL) {
    182        if (guac_kubernetes_append_endpoint_param(buffer,
    183                    length, "container", kubernetes_container))
    184            return 1;
    185    }
    186
    187    /* Append stdin, stdout and tty parameters */
    188    return (guac_kubernetes_append_endpoint_param(buffer, length, "stdin", "true"))
    189        || (guac_kubernetes_append_endpoint_param(buffer, length, "stdout", "true"))
    190        || (guac_kubernetes_append_endpoint_param(buffer, length, "tty", "true"));
    191}