When the TLS client certificate is used for LuCI authentication, ubus session 
login is called with

  username = subject name
  password = certificate hash
  mode = 'cert'

Extra parameter 'mode' is needed to differentiate a regular username/password 
login attempt from the client
certificate auth. Otherwise one could fake the certificate login using the 
standard username/password
method entering subject name as username and cert hash as password, both of 
which are public/known/not-secret.
Session login is successful if the password/certificate hash matches the one 
stored in the /etc/config/rpcd
file.

Signed-off-by: Luka Logar <[email protected]>
---
 session.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/session.c b/session.c
index 908e298..b577475 100644
--- a/session.c
+++ b/session.c
@@ -120,12 +120,14 @@ enum {
        RPC_L_USERNAME,
        RPC_L_PASSWORD,
        RPC_L_TIMEOUT,
+       RPC_L_MODE,
        __RPC_L_MAX,
 };
 static const struct blobmsg_policy login_policy[__RPC_L_MAX] = {
        [RPC_L_USERNAME] = { .name = "username", .type = BLOBMSG_TYPE_STRING },
        [RPC_L_PASSWORD] = { .name = "password", .type = BLOBMSG_TYPE_STRING },
        [RPC_L_TIMEOUT]  = { .name = "timeout", .type = BLOBMSG_TYPE_INT32 },
+       [RPC_L_MODE]     = { .name = "mode", .type = BLOBMSG_TYPE_STRING },
 };
 
 /*
@@ -827,7 +829,7 @@ rpc_login_test_password(const char *hash, const char 
*password)
 
 static struct uci_section *
 rpc_login_test_login(struct uci_context *uci,
-                     const char *username, const char *password)
+                     const char *username, const char *password, const char 
*mode)
 {
        struct uci_package *p = NULL;
        struct uci_section *s;
@@ -877,6 +879,13 @@ rpc_login_test_login(struct uci_context *uci,
                if (ptr.o->type != UCI_TYPE_STRING)
                        continue;
 
+               if (mode && !strcmp(mode, "cert"))
+               {
+                       if (!strcasecmp(ptr.o->v.string, password))
+                               return ptr.s;
+                       continue;
+               }
+
                if (rpc_login_test_password(ptr.o->v.string, password))
                        return ptr.s;
        }
@@ -1137,7 +1146,8 @@ rpc_handle_login(struct ubus_context *ctx, struct 
ubus_object *obj,
        }
 
        login = rpc_login_test_login(uci, 
blobmsg_get_string(tb[RPC_L_USERNAME]),
-                                         
blobmsg_get_string(tb[RPC_L_PASSWORD]));
+                                         
blobmsg_get_string(tb[RPC_L_PASSWORD]),
+                                         blobmsg_get_string(tb[RPC_L_MODE]));
 
        if (!login) {
                rv = UBUS_STATUS_PERMISSION_DENIED;
@@ -1296,7 +1306,7 @@ rpc_session_from_blob(struct uci_context *uci, struct 
blob_attr *attr)
        }
 
        if (uci && user) {
-               login = rpc_login_test_login(uci, user, NULL);
+               login = rpc_login_test_login(uci, user, NULL, NULL);
                if (login)
                        rpc_login_setup_acls(ses, login);
        }
-- 
2.25.1



_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to