Skip to content
Snippets Groups Projects
encryption_keys_put_post.c 4.31 KiB
Newer Older
/**
 * Combined handler for adding and changing luks encryption passwords.
 * @param[in]   request   incoming HTTP request
 * @param[out]  response  HTTP response to the request
 * @param[in]   is_post   this is a post request (true) or a put (false)
 * @return                internal status code
 */
int encryption_keys_change(const struct _u_request * request,
    struct _u_response * response, bool is_post)
{
    int r;

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

    // Read (current) password from request.
    const char * password;
    password = json_string_value(json_object_get(json_input, "password"));
    if (password == NULL)
    {
        return send_simple_response(response, 400, "error", "missing password");
    }

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

    int keyslot;
    // Posting a new password, put it in the first available slot.
    if (is_post)
    {
        keyslot = CRYPT_ANY_SLOT;
    }
    // Changing an existing password, so read the slot from the url.
    else
    {
        // Read keyslot from request URI.
        const char * keyslot_string = u_map_get(request->map_url, "slot");
        if (keyslot_string == NULL)
        {
            return send_simple_response(response, 400, "error",
                "missing url parameter `slot`");
        }
        r = parse_int(keyslot_string, &keyslot);
        if (r != 0)
        {
            printf("invalid url parameter `slot`: %s\n", keyslot_string);
            return send_simple_response(response, 400, "error",
                "invalid url parameter `slot`");
        }
    }

    // Initialise encrypted container.
    struct crypt_device * cd = NULL;
    r = container_initialise(&cd, DATA_PARTITION_DEVICE, true);
    if (r < 0)
    {
        crypt_free(cd);
    }
    if (r != 0)
    {
        printf("container_initialise failed with status %d\n", r);
        return send_simple_response(response, 500, "error",
            "initialising encrypted container failed");
    }

    if (is_post)
    {
        // Add encryption password.
        r = crypt_keyslot_add_by_passphrase(cd, keyslot,
            password, strlen(password), new_password, strlen(new_password));
    }
    else
    {
        // Change encryption password.
        r = crypt_keyslot_change_by_passphrase(cd, keyslot, keyslot,
            password, strlen(password), new_password, strlen(new_password));
    }
  
    if (r == -1)
    {
        // Experience learns that -1 is returned when the password is wrong.
        return send_simple_response(response, 403, "error",
           "incorrect password");
    }
  
    if (r < 0)
    {
        // Something else went wrong.
        if (is_post)
        {
            printf("crypt_keyslot_add_by_passphrase failed with status %d\n", r);
        }
        else
        {
            printf("crypt_keyslot_change_by_passphrase failed with status %d\n", r);
        }
        return send_simple_response(response, 500, "error",
            "error changing password");
    }
  
    // If we reach this point, apparently everything went well.
    return send_simple_response(response, 200, "status", "ok");
}

/**
 * Callback function to add a luks encryption password.
 * @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_encryption_keys_post(const struct _u_request * request,
    struct _u_response * response, void * user_data)
{
    return encryption_keys_change(request, response, true);
}
/**
 * Callback function to change a luks encryption password.
 * @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_encryption_keys_put(const struct _u_request * request,
    struct _u_response * response, void * user_data)
{
    return encryption_keys_change(request, response, false);
}