blob: 9196922381ed3afdd997d062d3a2eb8033654ba7 [file] [log] [blame]
Harald Weltee72cf552016-04-28 07:18:49 +02001/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
2 *
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <string.h>
21
22#include <osmocom/core/utils.h>
23#include <osmocom/crypt/auth.h>
24
25#include <sqlite3.h>
26
27#include "logging.h"
28#include "db.h"
29#include "auc.h"
30#include "rand.h"
31
32#define LOGAUC(imsi, level, fmt, args ...) LOGP(DAUC, level, "%s: " fmt, imsi, ## args)
33
34/* update the SQN for a given subscriber ID */
35int db_update_sqn(struct db_context *dbc, uint64_t id,
36 uint64_t new_sqn)
37{
38 sqlite3_stmt *stmt = dbc->stmt[AUC_UPD_SQN];
39 int rc;
40
41 /* bind new SQN and subscriber ID */
42 rc = sqlite3_bind_int64(stmt, 1, new_sqn);
43 if (rc != SQLITE_OK) {
44 LOGP(DAUC, LOGL_ERROR, "Error binding SQN: %d\n", rc);
45 return -1;
46 }
47
48 rc = sqlite3_bind_int64(stmt, 2, id);
49 if (rc != SQLITE_OK) {
50 LOGP(DAUC, LOGL_ERROR, "Error binding Subscrber ID: %d\n", rc);
51 return -1;
52 }
53
54 /* execute the statement */
55 rc = sqlite3_step(stmt);
56 if (rc != SQLITE_DONE) {
57 LOGP(DAUC, LOGL_ERROR, "Error updating SQN: %d\n", rc);
58 return -2;
59 }
60
61 /* remove bindings and reset statement to be re-executed */
62 rc = sqlite3_clear_bindings(stmt);
63 if (rc != SQLITE_OK) {
64 LOGP(DAUC, LOGL_ERROR, "Error clerearing bindings: %d\n", rc);
65 }
66 rc = sqlite3_reset(stmt);
67 if (rc != SQLITE_OK) {
68 LOGP(DAUC, LOGL_ERROR, "Error in sqlite3_reset: %d\n", rc);
69 }
70
71 return 0;
72}
73
Harald Weltecfc752b2016-05-05 16:38:14 +020074/* obtain the authentication data for a given imsi
75 * returns -1 in case of error, 0 for unknown IMSI, 1 for success */
Harald Weltee72cf552016-04-28 07:18:49 +020076int db_get_auth_data(struct db_context *dbc, const char *imsi,
77 struct osmo_sub_auth_data *aud2g,
78 struct osmo_sub_auth_data *aud3g,
79 uint64_t *subscr_id)
80{
81 sqlite3_stmt *stmt = dbc->stmt[AUC_BY_IMSI];
Harald Weltecfc752b2016-05-05 16:38:14 +020082 int ret = 0;
Harald Weltee72cf552016-04-28 07:18:49 +020083 int rc;
84
85 memset(aud2g, 0, sizeof(*aud2g));
86 memset(aud3g, 0, sizeof(*aud3g));
87
88 /* bind the IMSI value */
89 rc = sqlite3_bind_text(stmt, 1, imsi, -1,
90 SQLITE_STATIC);
91 if (rc != SQLITE_OK) {
92 LOGAUC(imsi, LOGL_ERROR, "Error binding IMSI: %d\n", rc);
Harald Weltecfc752b2016-05-05 16:38:14 +020093 ret = -1;
94 goto out;
Harald Weltee72cf552016-04-28 07:18:49 +020095 }
96
97 /* execute the statement */
98 rc = sqlite3_step(stmt);
Harald Weltecfc752b2016-05-05 16:38:14 +020099 if (rc == SQLITE_DONE) {
100 LOGAUC(imsi, LOGL_INFO, "Unknown\n");
101 ret = 0;
102 goto out;
103 } else if (rc != SQLITE_ROW) {
Harald Weltee72cf552016-04-28 07:18:49 +0200104 LOGAUC(imsi, LOGL_ERROR, "Error executing SQL: %d\n", rc);
Harald Weltecfc752b2016-05-05 16:38:14 +0200105 ret = -1;
Harald Weltee72cf552016-04-28 07:18:49 +0200106 goto out;
107 }
108
109 /* as an optimization, we retrieve the subscriber ID, to ensure we can
110 * update the SQN later without having to go back via a JOIN with the
111 * subscriber table. */
112 if (subscr_id)
113 *subscr_id = sqlite3_column_int64(stmt, 0);
114
Harald Weltee72cf552016-04-28 07:18:49 +0200115 /* obtain result values using sqlite3_column_*() */
116 if (sqlite3_column_type(stmt, 1) == SQLITE_INTEGER) {
117 /* we do have some 2G authentication data */
118 const uint8_t *ki;
119
120 aud2g->algo = sqlite3_column_int(stmt, 1);
121 ki = sqlite3_column_text(stmt, 2);
122#if 0
123 if (sqlite3_column_bytes(stmt, 2) != sizeof(aud2g->u.gsm.ki)) {
124 LOGAUC(imsi, LOGL_ERROR, "Error reading Ki: %d\n", rc);
125 goto end_2g;
126 }
127#endif
Harald Welte64f3ca32016-05-05 17:07:17 +0200128 osmo_hexparse(ki, &aud2g->u.gsm.ki, sizeof(aud2g->u.gsm.ki));
Harald Weltee72cf552016-04-28 07:18:49 +0200129 aud2g->type = OSMO_AUTH_TYPE_GSM;
130 } else
131 LOGAUC(imsi, LOGL_DEBUG, "No 2G Auth Data\n");
132//end_2g:
133 if (sqlite3_column_type(stmt, 3) == SQLITE_INTEGER) {
134 /* we do have some 3G authentication data */
135 const uint8_t *k, *op, *opc;
136
137 aud3g->algo = sqlite3_column_int(stmt, 3);
138 k = sqlite3_column_text(stmt, 4);
139 if (!k) {
140 LOGAUC(imsi, LOGL_ERROR, "Error reading K: %d\n", rc);
141 goto out;
142 }
Harald Welte64f3ca32016-05-05 17:07:17 +0200143 osmo_hexparse(k, &aud3g->u.umts.k, sizeof(aud3g->u.umts.k));
Harald Weltee72cf552016-04-28 07:18:49 +0200144 /* UMTS Subscribers can have either OP or OPC */
145 op = sqlite3_column_text(stmt, 5);
146 if (!op) {
147 opc = sqlite3_column_text(stmt, 6);
148 if (!opc) {
149 LOGAUC(imsi, LOGL_ERROR, "Error reading OPC: %d\n", rc);
150 goto out;
151 }
Harald Welte64f3ca32016-05-05 17:07:17 +0200152 osmo_hexparse(opc, &aud3g->u.umts.opc,
153 sizeof(aud3g->u.umts.opc));
Harald Weltee72cf552016-04-28 07:18:49 +0200154 aud3g->u.umts.opc_is_op = 0;
155 } else {
Harald Welte64f3ca32016-05-05 17:07:17 +0200156 osmo_hexparse(op, &aud3g->u.umts.opc,
157 sizeof(aud3g->u.umts.opc));
Harald Weltee72cf552016-04-28 07:18:49 +0200158 aud3g->u.umts.opc_is_op = 1;
159 }
160 aud3g->u.umts.sqn = sqlite3_column_int64(stmt, 7);
161 /* FIXME: amf? */
162 aud3g->type = OSMO_AUTH_TYPE_UMTS;
163 } else
164 LOGAUC(imsi, LOGL_DEBUG, "No 3G Auth Data\n");
Harald Weltecfc752b2016-05-05 16:38:14 +0200165
166 if (aud2g->type == 0 && aud3g->type == 0)
167 ret = -1;
168 else
169 ret = 1;
170
Harald Weltee72cf552016-04-28 07:18:49 +0200171out:
172 /* remove bindings and reset statement to be re-executed */
173 rc = sqlite3_clear_bindings(stmt);
174 if (rc != SQLITE_OK) {
175 LOGAUC(imsi, LOGL_ERROR, "Error in sqlite3_clear_bindings(): %d\n", rc);
176 }
177 rc = sqlite3_reset(stmt);
178 if (rc != SQLITE_OK) {
179 LOGAUC(imsi, LOGL_ERROR, "Error in sqlite3_reset(): %d\n", rc);
180 }
181
Harald Weltecfc752b2016-05-05 16:38:14 +0200182 return ret;
Harald Weltee72cf552016-04-28 07:18:49 +0200183}
184
Harald Weltecfc752b2016-05-05 16:38:14 +0200185/* return -1 in case of error, 0 for unknown imsi, positive for number
186 * of vectors generated */
Harald Weltee72cf552016-04-28 07:18:49 +0200187int db_get_auc(struct db_context *dbc, const char *imsi,
188 struct osmo_auth_vector *vec, unsigned int num_vec,
189 const uint8_t *rand_auts, const uint8_t *auts)
190{
191 struct osmo_sub_auth_data aud2g, aud3g;
192 uint64_t subscr_id;
Harald Weltecfc752b2016-05-05 16:38:14 +0200193 int ret = 0;
Harald Weltee72cf552016-04-28 07:18:49 +0200194 int rc;
195
196 rc = db_get_auth_data(dbc, imsi, &aud2g, &aud3g, &subscr_id);
Harald Weltecfc752b2016-05-05 16:38:14 +0200197 if (rc <= 0)
Harald Weltee72cf552016-04-28 07:18:49 +0200198 return rc;
199
200 LOGAUC(imsi, LOGL_INFO, "Calling to generate %u vectors\n", num_vec);
201 rc = auc_compute_vectors(vec, num_vec, &aud2g, &aud3g, rand_auts, auts);
Harald Weltecfc752b2016-05-05 16:38:14 +0200202 if (rc < 0) {
Harald Weltee72cf552016-04-28 07:18:49 +0200203 num_vec = 0;
Harald Weltecfc752b2016-05-05 16:38:14 +0200204 ret = -1;
205 } else {
Harald Weltee72cf552016-04-28 07:18:49 +0200206 num_vec = rc;
Harald Weltecfc752b2016-05-05 16:38:14 +0200207 ret = num_vec;
208 }
Harald Weltee72cf552016-04-28 07:18:49 +0200209 LOGAUC(imsi, LOGL_INFO, "Generated %u vectors\n", num_vec);
210
211 /* Update SQN in database, as needed */
212 if (aud3g.algo) {
213 LOGAUC(imsi, LOGL_DEBUG, "Updating SQN in DB\n");
214 rc = db_update_sqn(dbc, subscr_id, aud3g.u.umts.sqn);
215 /* don't tell caller we generated any triplets in case of
216 * update error */
217 if (rc < 0) {
218 LOGAUC(imsi, LOGL_ERROR, "Error updating SQN: %d\n", rc);
219 num_vec = 0;
Harald Weltecfc752b2016-05-05 16:38:14 +0200220 ret = -1;
Harald Weltee72cf552016-04-28 07:18:49 +0200221 }
222 }
223
Harald Weltecfc752b2016-05-05 16:38:14 +0200224 return ret;
Harald Weltee72cf552016-04-28 07:18:49 +0200225}