]> jfr.im git - solanum.git/blobdiff - authd/provider.c
chmode: Get elevated access for op-only queries
[solanum.git] / authd / provider.c
index 49fd5007961d61c66b46e3e13d433aa97dce6ffa..2d196732d217c3597d5a2525fac199af46e8d599 100644 (file)
@@ -19,7 +19,7 @@
  */
 
 /* The basic design here is to have "authentication providers" that do things
- * like query ident and blacklists and even open proxies.
+ * like query ident and DNSBLs and even open proxies.
  *
  * Providers are registered in the auth_providers linked list. It is planned to
  * use a bitmap to store provider ID's later.
@@ -62,6 +62,29 @@ static rb_dlink_list free_pids;
 static uint32_t allocated_pids;
 static struct ev_entry *timeout_ev;
 
+/* Set a provider's raw status */
+static inline void
+set_provider_status(struct auth_client *auth, uint32_t provider, provider_status_t status)
+{
+       auth->data[provider].status = status;
+}
+
+/* Set the provider as running */
+static inline void
+set_provider_running(struct auth_client *auth, uint32_t provider)
+{
+       auth->providers_active++;
+       set_provider_status(auth, provider, PROVIDER_STATUS_RUNNING);
+}
+
+/* Provider is no longer operating on this auth client */
+static inline void
+set_provider_done(struct auth_client *auth, uint32_t provider)
+{
+       set_provider_status(auth, provider, PROVIDER_STATUS_DONE);
+       auth->providers_active--;
+}
+
 /* Initalise all providers */
 void
 init_providers(void)
@@ -69,10 +92,13 @@ init_providers(void)
        auth_clients = rb_dictionary_create("pending auth clients", rb_uint32cmp);
        timeout_ev = rb_event_addish("provider_timeout_event", provider_timeout_event, NULL, 1);
 
+       /* FIXME must be started before rdns/ident to receive completion notification from them */
+       load_provider(&dnsbl_provider);
+       load_provider(&opm_provider);
+
+       /* FIXME must be started after dnsbl/opm in case of early completion notifications */
        load_provider(&rdns_provider);
        load_provider(&ident_provider);
-       load_provider(&blacklist_provider);
-       load_provider(&opm_provider);
 }
 
 /* Terminate all providers */
@@ -82,7 +108,6 @@ destroy_providers(void)
        rb_dlink_node *ptr, *nptr;
        rb_dictionary_iter iter;
        struct auth_client *auth;
-       struct auth_provider *provider;
 
        /* Cancel outstanding connections */
        RB_DICTIONARY_FOREACH(auth, &iter, auth_clients)
@@ -204,8 +229,7 @@ cancel_providers(struct auth_client *auth)
        }
 }
 
-/* Provider is done
- * WARNING: do not use auth instance after calling! */
+/* Provider is done */
 void
 provider_done(struct auth_client *auth, uint32_t id)
 {
@@ -234,8 +258,7 @@ provider_done(struct auth_client *auth, uint32_t id)
        }
 }
 
-/* Reject a client and cancel any outstanding providers
- * WARNING: do not use auth instance after calling! */
+/* Reject a client and cancel any outstanding providers */
 void
 reject_client(struct auth_client *auth, uint32_t id, const char *data, const char *fmt, ...)
 {
@@ -251,7 +274,7 @@ reject_client(struct auth_client *auth, uint32_t id, const char *data, const cha
         * --Elizafox
         */
        rb_helper_write(authd_helper, "R %x %c %s %s %s :%s",
-               auth->cid, auth->data[id].provider->letter,
+               auth->cid, id != UINT32_MAX ? auth->data[id].provider->letter : '*',
                auth->username, auth->hostname,
                data == NULL ? "*" : data, buf);
 
@@ -271,7 +294,7 @@ accept_client(struct auth_client *auth)
 
 /* Begin authenticating user */
 static void
-start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port)
+start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_ip, const char *c_port, const char *protocol)
 {
        struct auth_client *auth;
        unsigned long long lcid = strtoull(cid, NULL, 16);
@@ -292,14 +315,16 @@ start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_
                exit(EX_PROVIDER_ERROR);
        }
 
+       auth->protocol = strtoull(protocol, NULL, 16);
+
        rb_strlcpy(auth->l_ip, l_ip, sizeof(auth->l_ip));
        auth->l_port = (uint16_t)atoi(l_port);  /* should be safe */
-       (void) rb_inet_pton_sock(l_ip, (struct sockaddr *)&auth->l_addr);
+       (void) rb_inet_pton_sock(l_ip, &auth->l_addr);
        SET_SS_PORT(&auth->l_addr, htons(auth->l_port));
 
        rb_strlcpy(auth->c_ip, c_ip, sizeof(auth->c_ip));
        auth->c_port = (uint16_t)atoi(c_port);
-       (void) rb_inet_pton_sock(c_ip, (struct sockaddr *)&auth->c_addr);
+       (void) rb_inet_pton_sock(c_ip, &auth->c_addr);
        SET_SS_PORT(&auth->c_addr, htons(auth->c_port));
 
        rb_strlcpy(auth->hostname, "*", sizeof(auth->hostname));
@@ -317,6 +342,7 @@ start_auth(const char *cid, const char *l_ip, const char *l_port, const char *c_
                lrb_assert(provider->start != NULL);
 
                /* Execute providers */
+               set_provider_running(auth, provider->id);
                if(!provider->start(auth))
                        /* Rejected immediately */
                        goto done;
@@ -338,13 +364,12 @@ done:
 void
 handle_new_connection(int parc, char *parv[])
 {
-       if(parc < 6)
-       {
+       if (parc < 6) {
                warn_opers(L_CRIT, "provider: received too few params for new connection (6 expected, got %d)", parc);
                exit(EX_PROVIDER_ERROR);
        }
 
-       start_auth(parv[1], parv[2], parv[3], parv[4], parv[5]);
+       start_auth(parv[1], parv[2], parv[3], parv[4], parv[5], parc > 6 ? parv[6] : "0");
 }
 
 void