LCOV - code coverage report
Current view: top level - src/infrastructure - auth_logout.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 83.0 % 47 39
Test Date: 2026-04-20 19:54:22 Functions: 100.0 % 4 4

            Line data    Source code
       1              : /* SPDX-License-Identifier: GPL-3.0-or-later */
       2              : /* Copyright 2026 Peter Csaszar */
       3              : 
       4              : /**
       5              :  * @file infrastructure/auth_logout.c
       6              :  * @brief Server-side logout: auth.logOut#3e72ba19 + local session wipe.
       7              :  */
       8              : 
       9              : #include "auth_logout.h"
      10              : #include "app/session_store.h"
      11              : #include "mtproto_rpc.h"
      12              : #include "tl_serial.h"
      13              : #include "tl_registry.h"
      14              : #include "logger.h"
      15              : #include "raii.h"
      16              : 
      17              : #include <stdlib.h>
      18              : #include <string.h>
      19              : 
      20              : /* ---- Logout observer (Observer pattern keeps domain/ out of here) ---- */
      21              : 
      22              : static void (*s_on_logout_cb)(void) = NULL;
      23              : 
      24           10 : void auth_logout_set_cache_flush_cb(void (*cb)(void)) {
      25           10 :     s_on_logout_cb = cb;
      26           10 : }
      27              : 
      28              : /* ---- Build the auth.logOut TL request ---- */
      29              : 
      30           12 : static int build_logout_request(uint8_t *out, size_t max_len, size_t *out_len) {
      31              :     TlWriter w;
      32           12 :     tl_writer_init(&w);
      33              : 
      34              :     /* auth.logOut#3e72ba19  — no arguments */
      35           12 :     tl_write_uint32(&w, CRC_auth_logOut);
      36              : 
      37           12 :     if (w.len > max_len) {
      38            0 :         tl_writer_free(&w);
      39            0 :         return -1;
      40              :     }
      41           12 :     memcpy(out, w.data, w.len);
      42           12 :     *out_len = w.len;
      43           12 :     tl_writer_free(&w);
      44           12 :     return 0;
      45              : }
      46              : 
      47              : /* ---- auth_logout_rpc ---- */
      48              : 
      49           13 : int auth_logout_rpc(const ApiConfig *cfg, MtProtoSession *s, Transport *t) {
      50           13 :     if (!cfg || !s || !t) return -1;
      51              : 
      52              :     uint8_t query[64];
      53           12 :     size_t  qlen = 0;
      54           12 :     if (build_logout_request(query, sizeof(query), &qlen) != 0) {
      55            0 :         logger_log(LOG_ERROR, "auth_logout: failed to build request");
      56            0 :         return -1;
      57              :     }
      58              : 
      59           12 :     RAII_STRING uint8_t *resp = (uint8_t *)malloc(4096);
      60           12 :     if (!resp) return -1;
      61           12 :     size_t resp_len = 0;
      62              : 
      63           12 :     if (api_call(cfg, s, t, query, qlen, resp, 4096, &resp_len) != 0) {
      64            1 :         logger_log(LOG_WARN, "auth_logout: api_call failed");
      65            1 :         return -1;
      66              :     }
      67              : 
      68           11 :     if (resp_len < 4) {
      69            0 :         logger_log(LOG_WARN, "auth_logout: response too short (%zu bytes)", resp_len);
      70            0 :         return -1;
      71              :     }
      72              : 
      73              :     uint32_t constructor;
      74           11 :     memcpy(&constructor, resp, 4);
      75              : 
      76           11 :     if (constructor == TL_rpc_error) {
      77              :         RpcError err;
      78            4 :         rpc_parse_error(resp, resp_len, &err);
      79            4 :         logger_log(LOG_WARN, "auth_logout: RPC error %d: %s",
      80              :                    err.error_code, err.error_msg);
      81              :         /* AUTH_KEY_UNREGISTERED / NOT_AUTHORIZED mean the session is already
      82              :          * dead on the server — still counts as a successful logout. */
      83            4 :         if (err.error_code == 401) {
      84            1 :             logger_log(LOG_INFO, "auth_logout: session already invalid on server");
      85            1 :             return 0;
      86              :         }
      87            3 :         return -1;
      88              :     }
      89              : 
      90            7 :     if (constructor != CRC_auth_loggedOut) {
      91            0 :         logger_log(LOG_WARN, "auth_logout: unexpected constructor 0x%08x", constructor);
      92            0 :         return -1;
      93              :     }
      94              : 
      95              :     /* auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes
      96              :      * We intentionally ignore future_auth_token. */
      97            7 :     logger_log(LOG_INFO, "auth_logout: server confirmed logout");
      98            7 :     return 0;
      99              : }
     100              : 
     101              : /* ---- auth_logout ---- */
     102              : 
     103            6 : void auth_logout(const ApiConfig *cfg, MtProtoSession *s, Transport *t) {
     104            6 :     if (auth_logout_rpc(cfg, s, t) != 0) {
     105            2 :         logger_log(LOG_WARN,
     106              :                    "auth_logout: server invalidation failed; clearing local session anyway");
     107              :     }
     108            6 :     session_store_clear();
     109              :     /* Drop session-scoped caches. Infrastructure cannot depend on the
     110              :      * domain layer directly, so we do this through a registered callback
     111              :      * set by the calling binary. */
     112            6 :     if (s_on_logout_cb) s_on_logout_cb();
     113            6 : }
        

Generated by: LCOV version 2.0-1