ssh_keys_post.c 2.35 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
 * Callback function that appends an SSH key tot the list of keys authorised for
 * access to the initrd.
 *
 * Example output:
 * {"ssh-keys":{"1":"ssh-rsa AAAAB3... example@example.com",
 * "2":"ssh-rsa AAAAB3...","5":"command=\"/usr/bin/cryptops-client\" ssh-rsa
 *  AAAAB3... cryptops-test@greenhost"}}
 *
 * The indices correspond to line numbers of the authorized_keys file.
 * Missing indices (like 3 and 4 in the example) arise from empty lines in the
 * file; those are creted when keys are deleted.
 *
 * @param[in]   request   incoming HTTP request
 * @param[out]  response  HTTP response to the request
 * @param[in]   user_data extra data to pass between main thread and callbacks
 * @return                internal status code
 */
int callback_ssh_keys_post(const struct _u_request * request,
    struct _u_response * response, void * user_data)
{
22
23
    // Open file with append+read mode.
    FILE * authorized_keys = fopen(AUTHORIZED_KEYS_PATH, "a+");
24
25
26
27

    // Check if that succeeded.
    if (authorized_keys == NULL)
    {
28
        y_log_message(Y_LOG_LEVEL_ERROR,
29
            "Could not open authorized_keys file for writing");
30
        return send_simple_response(response, 500, "error",
Maarten de Waard's avatar
Maarten de Waard committed
31
            "error opening authorized_keys");
32
33
34
35
36
37
38
39
40
41
42
43
44
    }

    // Read in json request body.
    json_t * json_input = ulfius_get_json_body_request(request, NULL);

    // Read SSH key from request.
    const char * ssh_key;
    ssh_key = json_string_value(json_object_get(json_input, "ssh-key"));
    if (ssh_key == NULL)
    {
        return send_simple_response(response, 400, "error", "missing ssh-key");
    }

45
    // add cryptops-client command to ssh-key
46
47
    char * ssh_key_with_command;
    add_ssh_command(&ssh_key_with_command, ssh_key);
48

49
50
51
52
    // Read the last character of the authorized_keys file.
    fseek(authorized_keys, -1, SEEK_END);
    int last_char = fgetc(authorized_keys);

53
    // Write SSH key to file
54
55
56
57
58
59
60
61
62
63
    // Check if the authorized_keys file is empty or ends in a newline.
    if (last_char == EOF || last_char == '\n')
    {
        fprintf(authorized_keys, "%s\n", ssh_key_with_command);
    }
    else
    {
        // If not, prepend an extra newline.
        fprintf(authorized_keys, "\n%s\n", ssh_key_with_command);
    }
64
    fclose(authorized_keys);
Arie Peterson's avatar
Arie Peterson committed
65
66
    free(ssh_key_with_command);
    json_decref(json_input);
67
68
69

    return send_simple_response(response, 200, "status", "ok");
}