Line data Source code
1 : /* SPDX-License-Identifier: GPL-3.0-or-later */
2 : /* Copyright 2026 Peter Csaszar */
3 :
4 : /**
5 : * @file auth_transfer.c
6 : * @brief P10-04 — auth.exportAuthorization + auth.importAuthorization.
7 : */
8 :
9 : #include "auth_transfer.h"
10 :
11 : #include "tl_serial.h"
12 : #include "tl_registry.h"
13 : #include "logger.h"
14 : #include "raii.h"
15 :
16 : #include <stdlib.h>
17 : #include <string.h>
18 :
19 : /* TL constructor IDs (not yet in tl_registry). */
20 : #define CRC_auth_exportAuthorization 0xe5bfffcdu
21 : #define CRC_auth_exportedAuthorization 0xb434e2b8u
22 : #define CRC_auth_importAuthorization 0xa57a7dadu
23 : #define CRC_auth_authorization 0x2ea2c0d4u
24 : #define CRC_auth_authorizationSignUpRequired 0x44747e9au
25 :
26 : #define RESP_BUF_SIZE 65536
27 :
28 : /* ---- export ---- */
29 :
30 5 : int auth_transfer_export(const ApiConfig *cfg,
31 : MtProtoSession *home_s, Transport *home_t,
32 : int target_dc_id,
33 : AuthExported *out,
34 : RpcError *err) {
35 5 : if (!cfg || !home_s || !home_t || !out) return -1;
36 5 : if (err) { err->error_code = 0; err->error_msg[0] = '\0';
37 4 : err->migrate_dc = -1; err->flood_wait_secs = 0; }
38 5 : memset(out, 0, sizeof(*out));
39 :
40 : uint8_t query[64];
41 5 : TlWriter w; tl_writer_init(&w);
42 5 : tl_write_uint32(&w, CRC_auth_exportAuthorization);
43 5 : tl_write_int32 (&w, target_dc_id);
44 5 : if (w.len > sizeof(query)) { tl_writer_free(&w); return -1; }
45 5 : memcpy(query, w.data, w.len);
46 5 : size_t qlen = w.len;
47 5 : tl_writer_free(&w);
48 :
49 5 : RAII_STRING uint8_t *resp = (uint8_t *)malloc(RESP_BUF_SIZE);
50 5 : if (!resp) return -1;
51 5 : size_t resp_len = 0;
52 5 : if (api_call(cfg, home_s, home_t, query, qlen,
53 : resp, RESP_BUF_SIZE, &resp_len) != 0) {
54 0 : logger_log(LOG_ERROR, "auth_transfer_export: api_call failed");
55 0 : return -1;
56 : }
57 5 : if (resp_len < 4) return -1;
58 :
59 : uint32_t top;
60 5 : memcpy(&top, resp, 4);
61 5 : if (top == TL_rpc_error) {
62 0 : RpcError perr; rpc_parse_error(resp, resp_len, &perr);
63 0 : if (err) *err = perr;
64 0 : logger_log(LOG_ERROR, "auth_transfer_export: RPC %d: %s",
65 : perr.error_code, perr.error_msg);
66 0 : return -1;
67 : }
68 5 : if (top != CRC_auth_exportedAuthorization) {
69 0 : logger_log(LOG_ERROR,
70 : "auth_transfer_export: unexpected top 0x%08x", top);
71 0 : return -1;
72 : }
73 :
74 5 : TlReader r = tl_reader_init(resp, resp_len);
75 5 : tl_read_uint32(&r); /* constructor */
76 5 : out->id = tl_read_int64(&r);
77 :
78 5 : size_t bl = 0;
79 10 : RAII_STRING uint8_t *bytes = tl_read_bytes(&r, &bl);
80 5 : if (!bytes || bl == 0 || bl > AUTH_TRANSFER_BYTES_MAX) {
81 1 : logger_log(LOG_ERROR,
82 : "auth_transfer_export: bytes len %zu out of range", bl);
83 1 : return -1;
84 : }
85 4 : memcpy(out->bytes, bytes, bl);
86 4 : out->bytes_len = bl;
87 4 : logger_log(LOG_INFO,
88 : "auth_transfer_export: exported to DC%d (id=%lld, %zu bytes)",
89 4 : target_dc_id, (long long)out->id, bl);
90 4 : return 0;
91 : }
92 :
93 : /* ---- import ---- */
94 :
95 3 : int auth_transfer_import(const ApiConfig *cfg,
96 : MtProtoSession *s, Transport *t,
97 : const AuthExported *in,
98 : RpcError *err) {
99 3 : if (!cfg || !s || !t || !in) return -1;
100 3 : if (in->bytes_len == 0 || in->bytes_len > AUTH_TRANSFER_BYTES_MAX)
101 0 : return -1;
102 3 : if (err) { err->error_code = 0; err->error_msg[0] = '\0';
103 3 : err->migrate_dc = -1; err->flood_wait_secs = 0; }
104 :
105 3 : TlWriter w; tl_writer_init(&w);
106 3 : tl_write_uint32(&w, CRC_auth_importAuthorization);
107 3 : tl_write_int64 (&w, in->id);
108 3 : tl_write_bytes (&w, in->bytes, in->bytes_len);
109 :
110 3 : RAII_STRING uint8_t *query = (uint8_t *)malloc(w.len);
111 3 : if (!query) { tl_writer_free(&w); return -1; }
112 3 : memcpy(query, w.data, w.len);
113 3 : size_t qlen = w.len;
114 3 : tl_writer_free(&w);
115 :
116 3 : RAII_STRING uint8_t *resp = (uint8_t *)malloc(RESP_BUF_SIZE);
117 3 : if (!resp) return -1;
118 3 : size_t resp_len = 0;
119 3 : if (api_call(cfg, s, t, query, qlen,
120 : resp, RESP_BUF_SIZE, &resp_len) != 0) {
121 0 : logger_log(LOG_ERROR, "auth_transfer_import: api_call failed");
122 0 : return -1;
123 : }
124 3 : if (resp_len < 4) return -1;
125 :
126 : uint32_t top;
127 3 : memcpy(&top, resp, 4);
128 3 : if (top == TL_rpc_error) {
129 1 : RpcError perr; rpc_parse_error(resp, resp_len, &perr);
130 1 : if (err) *err = perr;
131 1 : logger_log(LOG_ERROR, "auth_transfer_import: RPC %d: %s",
132 : perr.error_code, perr.error_msg);
133 1 : return -1;
134 : }
135 2 : if (top != CRC_auth_authorization
136 1 : && top != CRC_auth_authorizationSignUpRequired) {
137 0 : logger_log(LOG_ERROR,
138 : "auth_transfer_import: unexpected top 0x%08x", top);
139 0 : return -1;
140 : }
141 2 : logger_log(LOG_INFO, "auth_transfer_import: foreign DC now authorized");
142 2 : return 0;
143 : }
|