1 /* 2 * Hotspot 2.0 SPP server 3 * Copyright (c) 2012-2013, Qualcomm Atheros, Inc. 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include <stdlib.h> 10 #include <stdio.h> 11 #include <string.h> 12 #include <ctype.h> 13 #include <time.h> 14 #include <errno.h> 15 #include <sqlite3.h> 16 17 #include "common.h" 18 #include "base64.h" 19 #include "md5_i.h" 20 #include "xml-utils.h" 21 #include "spp_server.h" 22 23 24 #define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp" 25 26 #define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0" 27 #define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0" 28 #define URN_OMA_DM_DMACC "urn:oma:mo:oma-dm-dmacc:1.0" 29 #define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0" 30 31 32 /* TODO: timeout to expire sessions */ 33 34 enum hs20_session_operation { 35 NO_OPERATION, 36 UPDATE_PASSWORD, 37 CONTINUE_SUBSCRIPTION_REMEDIATION, 38 CONTINUE_POLICY_UPDATE, 39 USER_REMEDIATION, 40 SUBSCRIPTION_REGISTRATION, 41 POLICY_REMEDIATION, 42 POLICY_UPDATE, 43 FREE_REMEDIATION, 44 CLEAR_REMEDIATION, 45 CERT_REENROLL, 46 }; 47 48 49 static char * db_get_session_val(struct hs20_svc *ctx, const char *user, 50 const char *realm, const char *session_id, 51 const char *field); 52 static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, 53 const char *field); 54 static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, 55 const char *realm, int use_dmacc); 56 static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, 57 const char *session_id, 58 const char *user, 59 const char *realm, 60 int add_est_user); 61 62 63 static int db_add_session(struct hs20_svc *ctx, 64 const char *user, const char *realm, 65 const char *sessionid, const char *pw, 66 const char *redirect_uri, 67 enum hs20_session_operation operation, 68 const u8 *mac_addr) 69 { 70 char *sql; 71 int ret = 0; 72 char addr[20]; 73 74 if (mac_addr) 75 snprintf(addr, sizeof(addr), MACSTR, MAC2STR(mac_addr)); 76 else 77 addr[0] = '\0'; 78 sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm," 79 "operation,password,redirect_uri,mac_addr,test) " 80 "VALUES " 81 "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," 82 "%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", 83 sessionid, user ? user : "", realm ? realm : "", 84 operation, pw ? pw : "", 85 redirect_uri ? redirect_uri : "", 86 addr, ctx->test); 87 if (sql == NULL) 88 return -1; 89 debug_print(ctx, 1, "DB: %s", sql); 90 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 91 debug_print(ctx, 1, "Failed to add session entry into sqlite " 92 "database: %s", sqlite3_errmsg(ctx->db)); 93 ret = -1; 94 } 95 sqlite3_free(sql); 96 return ret; 97 } 98 99 100 static void db_update_session_password(struct hs20_svc *ctx, const char *user, 101 const char *realm, const char *sessionid, 102 const char *pw) 103 { 104 char *sql; 105 106 sql = sqlite3_mprintf("UPDATE sessions SET password=%Q WHERE id=%Q AND " 107 "user=%Q AND realm=%Q", 108 pw, sessionid, user, realm); 109 if (sql == NULL) 110 return; 111 debug_print(ctx, 1, "DB: %s", sql); 112 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 113 debug_print(ctx, 1, "Failed to update session password: %s", 114 sqlite3_errmsg(ctx->db)); 115 } 116 sqlite3_free(sql); 117 } 118 119 120 static void db_update_session_machine_managed(struct hs20_svc *ctx, 121 const char *user, 122 const char *realm, 123 const char *sessionid, 124 const int pw_mm) 125 { 126 char *sql; 127 128 sql = sqlite3_mprintf("UPDATE sessions SET machine_managed=%Q WHERE id=%Q AND user=%Q AND realm=%Q", 129 pw_mm ? "1" : "0", sessionid, user, realm); 130 if (sql == NULL) 131 return; 132 debug_print(ctx, 1, "DB: %s", sql); 133 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 134 debug_print(ctx, 1, 135 "Failed to update session machine_managed: %s", 136 sqlite3_errmsg(ctx->db)); 137 } 138 sqlite3_free(sql); 139 } 140 141 142 static void db_add_session_pps(struct hs20_svc *ctx, const char *user, 143 const char *realm, const char *sessionid, 144 xml_node_t *node) 145 { 146 char *str; 147 char *sql; 148 149 str = xml_node_to_str(ctx->xml, node); 150 if (str == NULL) 151 return; 152 sql = sqlite3_mprintf("UPDATE sessions SET pps=%Q WHERE id=%Q AND " 153 "user=%Q AND realm=%Q", 154 str, sessionid, user, realm); 155 free(str); 156 if (sql == NULL) 157 return; 158 debug_print(ctx, 1, "DB: %s", sql); 159 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 160 debug_print(ctx, 1, "Failed to add session pps: %s", 161 sqlite3_errmsg(ctx->db)); 162 } 163 sqlite3_free(sql); 164 } 165 166 167 static void db_add_session_devinfo(struct hs20_svc *ctx, const char *sessionid, 168 xml_node_t *node) 169 { 170 char *str; 171 char *sql; 172 173 str = xml_node_to_str(ctx->xml, node); 174 if (str == NULL) 175 return; 176 sql = sqlite3_mprintf("UPDATE sessions SET devinfo=%Q WHERE id=%Q", 177 str, sessionid); 178 free(str); 179 if (sql == NULL) 180 return; 181 debug_print(ctx, 1, "DB: %s", sql); 182 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 183 debug_print(ctx, 1, "Failed to add session devinfo: %s", 184 sqlite3_errmsg(ctx->db)); 185 } 186 sqlite3_free(sql); 187 } 188 189 190 static void db_add_session_devdetail(struct hs20_svc *ctx, 191 const char *sessionid, 192 xml_node_t *node) 193 { 194 char *str; 195 char *sql; 196 197 str = xml_node_to_str(ctx->xml, node); 198 if (str == NULL) 199 return; 200 sql = sqlite3_mprintf("UPDATE sessions SET devdetail=%Q WHERE id=%Q", 201 str, sessionid); 202 free(str); 203 if (sql == NULL) 204 return; 205 debug_print(ctx, 1, "DB: %s", sql); 206 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 207 debug_print(ctx, 1, "Failed to add session devdetail: %s", 208 sqlite3_errmsg(ctx->db)); 209 } 210 sqlite3_free(sql); 211 } 212 213 214 static void db_add_session_dmacc(struct hs20_svc *ctx, const char *sessionid, 215 const char *username, const char *password) 216 { 217 char *sql; 218 219 sql = sqlite3_mprintf("UPDATE sessions SET osu_user=%Q, osu_password=%Q WHERE id=%Q", 220 username, password, sessionid); 221 if (!sql) 222 return; 223 debug_print(ctx, 1, "DB: %s", sql); 224 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 225 debug_print(ctx, 1, "Failed to add session DMAcc: %s", 226 sqlite3_errmsg(ctx->db)); 227 } 228 sqlite3_free(sql); 229 } 230 231 232 static void db_add_session_eap_method(struct hs20_svc *ctx, 233 const char *sessionid, 234 const char *method) 235 { 236 char *sql; 237 238 sql = sqlite3_mprintf("UPDATE sessions SET eap_method=%Q WHERE id=%Q", 239 method, sessionid); 240 if (!sql) 241 return; 242 debug_print(ctx, 1, "DB: %s", sql); 243 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 244 debug_print(ctx, 1, "Failed to add session EAP method: %s", 245 sqlite3_errmsg(ctx->db)); 246 } 247 sqlite3_free(sql); 248 } 249 250 251 static void db_add_session_id_hash(struct hs20_svc *ctx, const char *sessionid, 252 const char *id_hash) 253 { 254 char *sql; 255 256 sql = sqlite3_mprintf("UPDATE sessions SET mobile_identifier_hash=%Q WHERE id=%Q", 257 id_hash, sessionid); 258 if (!sql) 259 return; 260 debug_print(ctx, 1, "DB: %s", sql); 261 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 262 debug_print(ctx, 1, "Failed to add session ID hash: %s", 263 sqlite3_errmsg(ctx->db)); 264 } 265 sqlite3_free(sql); 266 } 267 268 269 static void db_remove_session(struct hs20_svc *ctx, 270 const char *user, const char *realm, 271 const char *sessionid) 272 { 273 char *sql; 274 275 if (user == NULL || realm == NULL) { 276 sql = sqlite3_mprintf("DELETE FROM sessions WHERE " 277 "id=%Q", sessionid); 278 } else { 279 sql = sqlite3_mprintf("DELETE FROM sessions WHERE " 280 "user=%Q AND realm=%Q AND id=%Q", 281 user, realm, sessionid); 282 } 283 if (sql == NULL) 284 return; 285 debug_print(ctx, 1, "DB: %s", sql); 286 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 287 debug_print(ctx, 1, "Failed to delete session entry from " 288 "sqlite database: %s", sqlite3_errmsg(ctx->db)); 289 } 290 sqlite3_free(sql); 291 } 292 293 294 static void hs20_eventlog(struct hs20_svc *ctx, 295 const char *user, const char *realm, 296 const char *sessionid, const char *notes, 297 const char *dump) 298 { 299 char *sql; 300 char *user_buf = NULL, *realm_buf = NULL; 301 302 debug_print(ctx, 1, "eventlog: %s", notes); 303 304 if (user == NULL) { 305 user_buf = db_get_session_val(ctx, NULL, NULL, sessionid, 306 "user"); 307 user = user_buf; 308 realm_buf = db_get_session_val(ctx, NULL, NULL, sessionid, 309 "realm"); 310 realm = realm_buf; 311 } 312 313 sql = sqlite3_mprintf("INSERT INTO eventlog" 314 "(user,realm,sessionid,timestamp,notes,dump,addr)" 315 " VALUES (%Q,%Q,%Q," 316 "strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," 317 "%Q,%Q,%Q)", 318 user, realm, sessionid, notes, 319 dump ? dump : "", ctx->addr ? ctx->addr : ""); 320 free(user_buf); 321 free(realm_buf); 322 if (sql == NULL) 323 return; 324 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 325 debug_print(ctx, 1, "Failed to add eventlog entry into sqlite " 326 "database: %s", sqlite3_errmsg(ctx->db)); 327 } 328 sqlite3_free(sql); 329 } 330 331 332 static void hs20_eventlog_node(struct hs20_svc *ctx, 333 const char *user, const char *realm, 334 const char *sessionid, const char *notes, 335 xml_node_t *node) 336 { 337 char *str; 338 339 if (node) 340 str = xml_node_to_str(ctx->xml, node); 341 else 342 str = NULL; 343 hs20_eventlog(ctx, user, realm, sessionid, notes, str); 344 free(str); 345 } 346 347 348 static void db_update_mo_str(struct hs20_svc *ctx, const char *user, 349 const char *realm, const char *name, 350 const char *str) 351 { 352 char *sql; 353 if (user == NULL || realm == NULL || name == NULL) 354 return; 355 sql = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE identity=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", 356 name, str, user, realm); 357 if (sql == NULL) 358 return; 359 debug_print(ctx, 1, "DB: %s", sql); 360 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 361 debug_print(ctx, 1, "Failed to update user MO entry in sqlite " 362 "database: %s", sqlite3_errmsg(ctx->db)); 363 } 364 sqlite3_free(sql); 365 } 366 367 368 static void db_update_mo(struct hs20_svc *ctx, const char *user, 369 const char *realm, const char *name, xml_node_t *mo) 370 { 371 char *str; 372 373 str = xml_node_to_str(ctx->xml, mo); 374 if (str == NULL) 375 return; 376 377 db_update_mo_str(ctx, user, realm, name, str); 378 free(str); 379 } 380 381 382 static void add_text_node(struct hs20_svc *ctx, xml_node_t *parent, 383 const char *name, const char *value) 384 { 385 xml_node_create_text(ctx->xml, parent, NULL, name, value ? value : ""); 386 } 387 388 389 static void add_text_node_conf(struct hs20_svc *ctx, const char *realm, 390 xml_node_t *parent, const char *name, 391 const char *field) 392 { 393 char *val; 394 val = db_get_osu_config_val(ctx, realm, field); 395 xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); 396 os_free(val); 397 } 398 399 400 static void add_text_node_conf_corrupt(struct hs20_svc *ctx, const char *realm, 401 xml_node_t *parent, const char *name, 402 const char *field) 403 { 404 char *val; 405 406 val = db_get_osu_config_val(ctx, realm, field); 407 if (val) { 408 size_t len; 409 410 len = os_strlen(val); 411 if (len > 0) { 412 if (val[len - 1] == '0') 413 val[len - 1] = '1'; 414 else 415 val[len - 1] = '0'; 416 } 417 } 418 xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); 419 os_free(val); 420 } 421 422 423 static int new_password(char *buf, int buflen) 424 { 425 int i; 426 427 if (buflen < 1) 428 return -1; 429 buf[buflen - 1] = '\0'; 430 if (os_get_random((unsigned char *) buf, buflen - 1) < 0) 431 return -1; 432 433 for (i = 0; i < buflen - 1; i++) { 434 unsigned char val = buf[i]; 435 val %= 2 * 26 + 10; 436 if (val < 26) 437 buf[i] = 'a' + val; 438 else if (val < 2 * 26) 439 buf[i] = 'A' + val - 26; 440 else 441 buf[i] = '0' + val - 2 * 26; 442 } 443 444 return 0; 445 } 446 447 448 struct get_db_field_data { 449 const char *field; 450 char *value; 451 }; 452 453 454 static int get_db_field(void *ctx, int argc, char *argv[], char *col[]) 455 { 456 struct get_db_field_data *data = ctx; 457 int i; 458 459 for (i = 0; i < argc; i++) { 460 if (os_strcmp(col[i], data->field) == 0 && argv[i]) { 461 os_free(data->value); 462 data->value = os_strdup(argv[i]); 463 break; 464 } 465 } 466 467 return 0; 468 } 469 470 471 static char * db_get_val(struct hs20_svc *ctx, const char *user, 472 const char *realm, const char *field, int dmacc) 473 { 474 char *cmd; 475 struct get_db_field_data data; 476 477 cmd = sqlite3_mprintf("SELECT %s FROM users WHERE %s=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", 478 field, dmacc ? "osu_user" : "identity", 479 user, realm); 480 if (cmd == NULL) 481 return NULL; 482 memset(&data, 0, sizeof(data)); 483 data.field = field; 484 if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) 485 { 486 debug_print(ctx, 1, "Could not find user '%s'", user); 487 sqlite3_free(cmd); 488 return NULL; 489 } 490 sqlite3_free(cmd); 491 492 debug_print(ctx, 1, "DB: user='%s' realm='%s' field='%s' dmacc=%d --> " 493 "value='%s'", user, realm, field, dmacc, data.value); 494 495 return data.value; 496 } 497 498 499 static int db_update_val(struct hs20_svc *ctx, const char *user, 500 const char *realm, const char *field, 501 const char *val, int dmacc) 502 { 503 char *cmd; 504 int ret; 505 506 cmd = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE %s=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", 507 field, val, dmacc ? "osu_user" : "identity", user, 508 realm); 509 if (cmd == NULL) 510 return -1; 511 debug_print(ctx, 1, "DB: %s", cmd); 512 if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { 513 debug_print(ctx, 1, 514 "Failed to update user in sqlite database: %s", 515 sqlite3_errmsg(ctx->db)); 516 ret = -1; 517 } else { 518 debug_print(ctx, 1, 519 "DB: user='%s' realm='%s' field='%s' set to '%s'", 520 user, realm, field, val); 521 ret = 0; 522 } 523 sqlite3_free(cmd); 524 525 return ret; 526 } 527 528 529 static char * db_get_session_val(struct hs20_svc *ctx, const char *user, 530 const char *realm, const char *session_id, 531 const char *field) 532 { 533 char *cmd; 534 struct get_db_field_data data; 535 536 if (user == NULL || realm == NULL) { 537 cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " 538 "id=%Q", field, session_id); 539 } else { 540 cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " 541 "user=%Q AND realm=%Q AND id=%Q", 542 field, user, realm, session_id); 543 } 544 if (cmd == NULL) 545 return NULL; 546 debug_print(ctx, 1, "DB: %s", cmd); 547 memset(&data, 0, sizeof(data)); 548 data.field = field; 549 if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) 550 { 551 debug_print(ctx, 1, "DB: Could not find session %s: %s", 552 session_id, sqlite3_errmsg(ctx->db)); 553 sqlite3_free(cmd); 554 return NULL; 555 } 556 sqlite3_free(cmd); 557 558 debug_print(ctx, 1, "DB: return '%s'", data.value); 559 return data.value; 560 } 561 562 563 static int update_password(struct hs20_svc *ctx, const char *user, 564 const char *realm, const char *pw, int dmacc) 565 { 566 char *cmd; 567 568 cmd = sqlite3_mprintf("UPDATE users SET password=%Q, " 569 "remediation='' " 570 "WHERE %s=%Q AND phase2=1", 571 pw, dmacc ? "osu_user" : "identity", 572 user); 573 if (cmd == NULL) 574 return -1; 575 debug_print(ctx, 1, "DB: %s", cmd); 576 if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { 577 debug_print(ctx, 1, "Failed to update database for user '%s'", 578 user); 579 } 580 sqlite3_free(cmd); 581 582 return 0; 583 } 584 585 586 static int clear_remediation(struct hs20_svc *ctx, const char *user, 587 const char *realm, int dmacc) 588 { 589 char *cmd; 590 591 cmd = sqlite3_mprintf("UPDATE users SET remediation='' WHERE %s=%Q", 592 dmacc ? "osu_user" : "identity", 593 user); 594 if (cmd == NULL) 595 return -1; 596 debug_print(ctx, 1, "DB: %s", cmd); 597 if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { 598 debug_print(ctx, 1, "Failed to update database for user '%s'", 599 user); 600 } 601 sqlite3_free(cmd); 602 603 return 0; 604 } 605 606 607 static int add_eap_ttls(struct hs20_svc *ctx, xml_node_t *parent) 608 { 609 xml_node_t *node; 610 611 node = xml_node_create(ctx->xml, parent, NULL, "EAPMethod"); 612 if (node == NULL) 613 return -1; 614 615 add_text_node(ctx, node, "EAPType", "21"); 616 add_text_node(ctx, node, "InnerMethod", "MS-CHAP-V2"); 617 618 return 0; 619 } 620 621 622 static xml_node_t * build_username_password(struct hs20_svc *ctx, 623 xml_node_t *parent, 624 const char *user, const char *pw) 625 { 626 xml_node_t *node; 627 char *b64; 628 size_t len; 629 630 node = xml_node_create(ctx->xml, parent, NULL, "UsernamePassword"); 631 if (node == NULL) 632 return NULL; 633 634 add_text_node(ctx, node, "Username", user); 635 636 b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL); 637 if (b64 == NULL) 638 return NULL; 639 len = os_strlen(b64); 640 if (len > 0 && b64[len - 1] == '\n') 641 b64[len - 1] = '\0'; 642 add_text_node(ctx, node, "Password", b64); 643 free(b64); 644 645 return node; 646 } 647 648 649 static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred, 650 const char *user, const char *pw, 651 int machine_managed) 652 { 653 xml_node_t *node; 654 655 node = build_username_password(ctx, cred, user, pw); 656 if (node == NULL) 657 return -1; 658 659 add_text_node(ctx, node, "MachineManaged", 660 machine_managed ? "TRUE" : "FALSE"); 661 add_text_node(ctx, node, "SoftTokenApp", ""); 662 add_eap_ttls(ctx, node); 663 664 return 0; 665 } 666 667 668 static void add_creation_date(struct hs20_svc *ctx, xml_node_t *cred) 669 { 670 char str[30]; 671 time_t now; 672 struct tm tm; 673 674 time(&now); 675 gmtime_r(&now, &tm); 676 snprintf(str, sizeof(str), "%04u-%02u-%02uT%02u:%02u:%02uZ", 677 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 678 tm.tm_hour, tm.tm_min, tm.tm_sec); 679 xml_node_create_text(ctx->xml, cred, NULL, "CreationDate", str); 680 } 681 682 683 static xml_node_t * build_credential_pw(struct hs20_svc *ctx, 684 const char *user, const char *realm, 685 const char *pw, int machine_managed) 686 { 687 xml_node_t *cred; 688 689 cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); 690 if (cred == NULL) { 691 debug_print(ctx, 1, "Failed to create Credential node"); 692 return NULL; 693 } 694 add_creation_date(ctx, cred); 695 if (add_username_password(ctx, cred, user, pw, machine_managed) < 0) { 696 xml_node_free(ctx->xml, cred); 697 return NULL; 698 } 699 add_text_node(ctx, cred, "Realm", realm); 700 701 return cred; 702 } 703 704 705 static xml_node_t * build_credential(struct hs20_svc *ctx, 706 const char *user, const char *realm, 707 char *new_pw, size_t new_pw_len) 708 { 709 if (new_password(new_pw, new_pw_len) < 0) 710 return NULL; 711 debug_print(ctx, 1, "Update password to '%s'", new_pw); 712 return build_credential_pw(ctx, user, realm, new_pw, 1); 713 } 714 715 716 static xml_node_t * build_credential_cert(struct hs20_svc *ctx, 717 const char *user, const char *realm, 718 const char *cert_fingerprint) 719 { 720 xml_node_t *cred, *cert; 721 722 cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); 723 if (cred == NULL) { 724 debug_print(ctx, 1, "Failed to create Credential node"); 725 return NULL; 726 } 727 add_creation_date(ctx, cred); 728 cert = xml_node_create(ctx->xml, cred, NULL, "DigitalCertificate"); 729 add_text_node(ctx, cert, "CertificateType", "x509v3"); 730 add_text_node(ctx, cert, "CertSHA256Fingerprint", cert_fingerprint); 731 add_text_node(ctx, cred, "Realm", realm); 732 733 return cred; 734 } 735 736 737 static xml_node_t * build_post_dev_data_response(struct hs20_svc *ctx, 738 xml_namespace_t **ret_ns, 739 const char *session_id, 740 const char *status, 741 const char *error_code) 742 { 743 xml_node_t *spp_node = NULL; 744 xml_namespace_t *ns; 745 746 spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, 747 "sppPostDevDataResponse"); 748 if (spp_node == NULL) 749 return NULL; 750 if (ret_ns) 751 *ret_ns = ns; 752 753 xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); 754 xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); 755 xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); 756 757 if (error_code) { 758 xml_node_t *node; 759 node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); 760 if (node) 761 xml_node_add_attr(ctx->xml, node, NULL, "errorCode", 762 error_code); 763 } 764 765 return spp_node; 766 } 767 768 769 static int add_update_node(struct hs20_svc *ctx, xml_node_t *spp_node, 770 xml_namespace_t *ns, const char *uri, 771 xml_node_t *upd_node) 772 { 773 xml_node_t *node, *tnds; 774 char *str; 775 776 tnds = mo_to_tnds(ctx->xml, upd_node, 0, NULL, NULL); 777 if (!tnds) 778 return -1; 779 780 str = xml_node_to_str(ctx->xml, tnds); 781 xml_node_free(ctx->xml, tnds); 782 if (str == NULL) 783 return -1; 784 node = xml_node_create_text(ctx->xml, spp_node, ns, "updateNode", str); 785 free(str); 786 787 xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", uri); 788 789 return 0; 790 } 791 792 793 static xml_node_t * read_subrem_file(struct hs20_svc *ctx, 794 const char *subrem_id, 795 char *uri, size_t uri_size) 796 { 797 char fname[200]; 798 char *buf, *buf2, *pos; 799 size_t len; 800 xml_node_t *node; 801 802 os_snprintf(fname, sizeof(fname), "%s/spp/subrem/%s", 803 ctx->root_dir, subrem_id); 804 debug_print(ctx, 1, "Use subrem file %s", fname); 805 806 buf = os_readfile(fname, &len); 807 if (!buf) 808 return NULL; 809 buf2 = os_realloc(buf, len + 1); 810 if (!buf2) { 811 os_free(buf); 812 return NULL; 813 } 814 buf = buf2; 815 buf[len] = '\0'; 816 817 pos = os_strchr(buf, '\n'); 818 if (!pos) { 819 os_free(buf); 820 return NULL; 821 } 822 *pos++ = '\0'; 823 os_strlcpy(uri, buf, uri_size); 824 825 node = xml_node_from_buf(ctx->xml, pos); 826 os_free(buf); 827 828 return node; 829 } 830 831 832 static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx, 833 const char *user, const char *realm, 834 const char *session_id, 835 int machine_rem, int dmacc) 836 { 837 xml_namespace_t *ns; 838 xml_node_t *spp_node, *cred; 839 char buf[400]; 840 char new_pw[33]; 841 char *status; 842 char *cert; 843 844 cert = db_get_val(ctx, user, realm, "cert", dmacc); 845 if (cert && cert[0] == '\0') { 846 os_free(cert); 847 cert = NULL; 848 } 849 if (cert) { 850 char *subrem; 851 852 /* No change needed in PPS MO unless specifically asked to */ 853 cred = NULL; 854 buf[0] = '\0'; 855 856 subrem = db_get_val(ctx, user, realm, "subrem", dmacc); 857 if (subrem && subrem[0]) { 858 cred = read_subrem_file(ctx, subrem, buf, sizeof(buf)); 859 if (!cred) { 860 debug_print(ctx, 1, 861 "Could not create updateNode from subrem file"); 862 os_free(subrem); 863 os_free(cert); 864 return NULL; 865 } 866 } 867 os_free(subrem); 868 } else { 869 char *real_user = NULL; 870 char *pw; 871 872 if (dmacc) { 873 real_user = db_get_val(ctx, user, realm, "identity", 874 dmacc); 875 if (!real_user) { 876 debug_print(ctx, 1, 877 "Could not find user identity for dmacc user '%s'", 878 user); 879 return NULL; 880 } 881 } 882 883 pw = db_get_session_val(ctx, user, realm, session_id, 884 "password"); 885 if (pw && pw[0]) { 886 debug_print(ctx, 1, "New password from the user: '%s'", 887 pw); 888 snprintf(new_pw, sizeof(new_pw), "%s", pw); 889 free(pw); 890 cred = build_credential_pw(ctx, 891 real_user ? real_user : user, 892 realm, new_pw, 0); 893 } else { 894 cred = build_credential(ctx, 895 real_user ? real_user : user, 896 realm, new_pw, sizeof(new_pw)); 897 } 898 899 free(real_user); 900 if (!cred) { 901 debug_print(ctx, 1, "Could not build credential"); 902 os_free(cert); 903 return NULL; 904 } 905 906 snprintf(buf, sizeof(buf), 907 "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", 908 realm); 909 } 910 911 status = "Remediation complete, request sppUpdateResponse"; 912 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 913 NULL); 914 if (spp_node == NULL) { 915 debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); 916 os_free(cert); 917 return NULL; 918 } 919 920 if ((cred && add_update_node(ctx, spp_node, ns, buf, cred) < 0) || 921 (!cred && !xml_node_create(ctx->xml, spp_node, ns, "noMOUpdate"))) { 922 debug_print(ctx, 1, "Could not add update node"); 923 xml_node_free(ctx->xml, spp_node); 924 os_free(cert); 925 return NULL; 926 } 927 928 hs20_eventlog_node(ctx, user, realm, session_id, 929 machine_rem ? "machine remediation" : 930 "user remediation", cred); 931 xml_node_free(ctx->xml, cred); 932 933 if (cert) { 934 debug_print(ctx, 1, "Request DB remediation clearing on success notification (certificate credential)"); 935 db_add_session(ctx, user, realm, session_id, NULL, NULL, 936 CLEAR_REMEDIATION, NULL); 937 } else { 938 debug_print(ctx, 1, "Request DB password update on success " 939 "notification"); 940 db_add_session(ctx, user, realm, session_id, new_pw, NULL, 941 UPDATE_PASSWORD, NULL); 942 } 943 os_free(cert); 944 945 return spp_node; 946 } 947 948 949 static xml_node_t * machine_remediation(struct hs20_svc *ctx, 950 const char *user, 951 const char *realm, 952 const char *session_id, int dmacc) 953 { 954 return build_sub_rem_resp(ctx, user, realm, session_id, 1, dmacc); 955 } 956 957 958 static xml_node_t * cert_reenroll(struct hs20_svc *ctx, 959 const char *user, 960 const char *realm, 961 const char *session_id) 962 { 963 db_add_session(ctx, user, realm, session_id, NULL, NULL, 964 CERT_REENROLL, NULL); 965 return spp_exec_get_certificate(ctx, session_id, user, realm, 0); 966 } 967 968 969 static xml_node_t * policy_remediation(struct hs20_svc *ctx, 970 const char *user, const char *realm, 971 const char *session_id, int dmacc) 972 { 973 xml_namespace_t *ns; 974 xml_node_t *spp_node, *policy; 975 char buf[400]; 976 const char *status; 977 978 hs20_eventlog(ctx, user, realm, session_id, 979 "requires policy remediation", NULL); 980 981 db_add_session(ctx, user, realm, session_id, NULL, NULL, 982 POLICY_REMEDIATION, NULL); 983 984 policy = build_policy(ctx, user, realm, dmacc); 985 if (!policy) { 986 return build_post_dev_data_response( 987 ctx, NULL, session_id, 988 "No update available at this time", NULL); 989 } 990 991 status = "Remediation complete, request sppUpdateResponse"; 992 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 993 NULL); 994 if (spp_node == NULL) 995 return NULL; 996 997 snprintf(buf, sizeof(buf), 998 "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy", 999 realm); 1000 1001 if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { 1002 xml_node_free(ctx->xml, spp_node); 1003 xml_node_free(ctx->xml, policy); 1004 return NULL; 1005 } 1006 1007 hs20_eventlog_node(ctx, user, realm, session_id, 1008 "policy update (sub rem)", policy); 1009 xml_node_free(ctx->xml, policy); 1010 1011 return spp_node; 1012 } 1013 1014 1015 static xml_node_t * browser_remediation(struct hs20_svc *ctx, 1016 const char *session_id, 1017 const char *redirect_uri, 1018 const char *uri) 1019 { 1020 xml_namespace_t *ns; 1021 xml_node_t *spp_node, *exec_node; 1022 1023 if (redirect_uri == NULL) { 1024 debug_print(ctx, 1, "Missing redirectURI attribute for user " 1025 "remediation"); 1026 return NULL; 1027 } 1028 debug_print(ctx, 1, "redirectURI %s", redirect_uri); 1029 1030 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1031 NULL); 1032 if (spp_node == NULL) 1033 return NULL; 1034 1035 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1036 xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", 1037 uri); 1038 return spp_node; 1039 } 1040 1041 1042 static xml_node_t * user_remediation(struct hs20_svc *ctx, const char *user, 1043 const char *realm, const char *session_id, 1044 const char *redirect_uri) 1045 { 1046 char uri[300], *val; 1047 1048 hs20_eventlog(ctx, user, realm, session_id, 1049 "requires user remediation", NULL); 1050 val = db_get_osu_config_val(ctx, realm, "remediation_url"); 1051 if (val == NULL) 1052 return NULL; 1053 1054 db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, 1055 USER_REMEDIATION, NULL); 1056 1057 snprintf(uri, sizeof(uri), "%s%s", val, session_id); 1058 os_free(val); 1059 return browser_remediation(ctx, session_id, redirect_uri, uri); 1060 } 1061 1062 1063 static xml_node_t * free_remediation(struct hs20_svc *ctx, 1064 const char *user, const char *realm, 1065 const char *session_id, 1066 const char *redirect_uri) 1067 { 1068 char uri[300], *val; 1069 1070 hs20_eventlog(ctx, user, realm, session_id, 1071 "requires free/public account remediation", NULL); 1072 val = db_get_osu_config_val(ctx, realm, "free_remediation_url"); 1073 if (val == NULL) 1074 return NULL; 1075 1076 db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, 1077 FREE_REMEDIATION, NULL); 1078 1079 snprintf(uri, sizeof(uri), "%s%s", val, session_id); 1080 os_free(val); 1081 return browser_remediation(ctx, session_id, redirect_uri, uri); 1082 } 1083 1084 1085 static xml_node_t * no_sub_rem(struct hs20_svc *ctx, 1086 const char *user, const char *realm, 1087 const char *session_id) 1088 { 1089 const char *status; 1090 1091 hs20_eventlog(ctx, user, realm, session_id, 1092 "no subscription mediation available", NULL); 1093 1094 status = "No update available at this time"; 1095 return build_post_dev_data_response(ctx, NULL, session_id, status, 1096 NULL); 1097 } 1098 1099 1100 static xml_node_t * hs20_subscription_remediation(struct hs20_svc *ctx, 1101 const char *user, 1102 const char *realm, 1103 const char *session_id, 1104 int dmacc, 1105 const char *redirect_uri) 1106 { 1107 char *type, *identity; 1108 xml_node_t *ret; 1109 char *free_account; 1110 1111 identity = db_get_val(ctx, user, realm, "identity", dmacc); 1112 if (identity == NULL || strlen(identity) == 0) { 1113 hs20_eventlog(ctx, user, realm, session_id, 1114 "user not found in database for remediation", 1115 NULL); 1116 os_free(identity); 1117 return build_post_dev_data_response(ctx, NULL, session_id, 1118 "Error occurred", 1119 "Not found"); 1120 } 1121 os_free(identity); 1122 1123 free_account = db_get_osu_config_val(ctx, realm, "free_account"); 1124 if (free_account && strcmp(free_account, user) == 0) { 1125 free(free_account); 1126 return no_sub_rem(ctx, user, realm, session_id); 1127 } 1128 free(free_account); 1129 1130 type = db_get_val(ctx, user, realm, "remediation", dmacc); 1131 if (type && strcmp(type, "free") != 0) { 1132 char *val; 1133 int shared = 0; 1134 val = db_get_val(ctx, user, realm, "shared", dmacc); 1135 if (val) 1136 shared = atoi(val); 1137 free(val); 1138 if (shared) { 1139 free(type); 1140 return no_sub_rem(ctx, user, realm, session_id); 1141 } 1142 } 1143 if (type && strcmp(type, "user") == 0) 1144 ret = user_remediation(ctx, user, realm, session_id, 1145 redirect_uri); 1146 else if (type && strcmp(type, "free") == 0) 1147 ret = free_remediation(ctx, user, realm, session_id, 1148 redirect_uri); 1149 else if (type && strcmp(type, "policy") == 0) 1150 ret = policy_remediation(ctx, user, realm, session_id, dmacc); 1151 else if (type && strcmp(type, "machine") == 0) 1152 ret = machine_remediation(ctx, user, realm, session_id, dmacc); 1153 else if (type && strcmp(type, "reenroll") == 0) 1154 ret = cert_reenroll(ctx, user, realm, session_id); 1155 else 1156 ret = no_sub_rem(ctx, user, realm, session_id); 1157 free(type); 1158 1159 return ret; 1160 } 1161 1162 1163 static xml_node_t * read_policy_file(struct hs20_svc *ctx, 1164 const char *policy_id) 1165 { 1166 char fname[200]; 1167 1168 snprintf(fname, sizeof(fname), "%s/spp/policy/%s.xml", 1169 ctx->root_dir, policy_id); 1170 debug_print(ctx, 1, "Use policy file %s", fname); 1171 1172 return node_from_file(ctx->xml, fname); 1173 } 1174 1175 1176 static void update_policy_update_uri(struct hs20_svc *ctx, const char *realm, 1177 xml_node_t *policy) 1178 { 1179 xml_node_t *node; 1180 char *url; 1181 1182 node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate/URI"); 1183 if (!node) 1184 return; 1185 1186 url = db_get_osu_config_val(ctx, realm, "policy_url"); 1187 if (!url) 1188 return; 1189 xml_node_set_text(ctx->xml, node, url); 1190 free(url); 1191 } 1192 1193 1194 static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, 1195 const char *realm, int use_dmacc) 1196 { 1197 char *policy_id; 1198 xml_node_t *policy, *node; 1199 1200 policy_id = db_get_val(ctx, user, realm, "policy", use_dmacc); 1201 if (policy_id == NULL || strlen(policy_id) == 0) { 1202 free(policy_id); 1203 policy_id = strdup("default"); 1204 if (policy_id == NULL) 1205 return NULL; 1206 } 1207 policy = read_policy_file(ctx, policy_id); 1208 free(policy_id); 1209 if (policy == NULL) 1210 return NULL; 1211 1212 update_policy_update_uri(ctx, realm, policy); 1213 1214 node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate"); 1215 if (node && use_dmacc) { 1216 char *pw; 1217 pw = db_get_val(ctx, user, realm, "osu_password", use_dmacc); 1218 if (pw == NULL || 1219 build_username_password(ctx, node, user, pw) == NULL) { 1220 debug_print(ctx, 1, "Failed to add Policy/PolicyUpdate/" 1221 "UsernamePassword"); 1222 free(pw); 1223 xml_node_free(ctx->xml, policy); 1224 return NULL; 1225 } 1226 free(pw); 1227 } 1228 1229 return policy; 1230 } 1231 1232 1233 static xml_node_t * hs20_policy_update(struct hs20_svc *ctx, 1234 const char *user, const char *realm, 1235 const char *session_id, int dmacc) 1236 { 1237 xml_namespace_t *ns; 1238 xml_node_t *spp_node; 1239 xml_node_t *policy; 1240 char buf[400]; 1241 const char *status; 1242 char *identity; 1243 1244 identity = db_get_val(ctx, user, realm, "identity", dmacc); 1245 if (identity == NULL || strlen(identity) == 0) { 1246 hs20_eventlog(ctx, user, realm, session_id, 1247 "user not found in database for policy update", 1248 NULL); 1249 os_free(identity); 1250 return build_post_dev_data_response(ctx, NULL, session_id, 1251 "Error occurred", 1252 "Not found"); 1253 } 1254 os_free(identity); 1255 1256 policy = build_policy(ctx, user, realm, dmacc); 1257 if (!policy) { 1258 return build_post_dev_data_response( 1259 ctx, NULL, session_id, 1260 "No update available at this time", NULL); 1261 } 1262 1263 db_add_session(ctx, user, realm, session_id, NULL, NULL, POLICY_UPDATE, 1264 NULL); 1265 1266 status = "Update complete, request sppUpdateResponse"; 1267 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1268 NULL); 1269 if (spp_node == NULL) 1270 return NULL; 1271 1272 snprintf(buf, sizeof(buf), 1273 "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy", 1274 realm); 1275 1276 if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { 1277 xml_node_free(ctx->xml, spp_node); 1278 xml_node_free(ctx->xml, policy); 1279 return NULL; 1280 } 1281 1282 hs20_eventlog_node(ctx, user, realm, session_id, "policy update", 1283 policy); 1284 xml_node_free(ctx->xml, policy); 1285 1286 return spp_node; 1287 } 1288 1289 1290 static xml_node_t * spp_get_mo(struct hs20_svc *ctx, xml_node_t *node, 1291 const char *urn, int *valid, char **ret_err) 1292 { 1293 xml_node_t *child, *tnds, *mo; 1294 const char *name; 1295 char *mo_urn; 1296 char *str; 1297 char fname[200]; 1298 1299 *valid = -1; 1300 if (ret_err) 1301 *ret_err = NULL; 1302 1303 xml_node_for_each_child(ctx->xml, child, node) { 1304 xml_node_for_each_check(ctx->xml, child); 1305 name = xml_node_get_localname(ctx->xml, child); 1306 if (strcmp(name, "moContainer") != 0) 1307 continue; 1308 mo_urn = xml_node_get_attr_value_ns(ctx->xml, child, SPP_NS_URI, 1309 "moURN"); 1310 if (strcasecmp(urn, mo_urn) == 0) { 1311 xml_node_get_attr_value_free(ctx->xml, mo_urn); 1312 break; 1313 } 1314 xml_node_get_attr_value_free(ctx->xml, mo_urn); 1315 } 1316 1317 if (child == NULL) 1318 return NULL; 1319 1320 debug_print(ctx, 1, "moContainer text for %s", urn); 1321 debug_dump_node(ctx, "moContainer", child); 1322 1323 str = xml_node_get_text(ctx->xml, child); 1324 debug_print(ctx, 1, "moContainer payload: '%s'", str); 1325 tnds = xml_node_from_buf(ctx->xml, str); 1326 xml_node_get_text_free(ctx->xml, str); 1327 if (tnds == NULL) { 1328 debug_print(ctx, 1, "could not parse moContainer text"); 1329 return NULL; 1330 } 1331 1332 snprintf(fname, sizeof(fname), "%s/spp/dm_ddf-v1_2.dtd", ctx->root_dir); 1333 if (xml_validate_dtd(ctx->xml, tnds, fname, ret_err) == 0) 1334 *valid = 1; 1335 else if (ret_err && *ret_err && 1336 os_strcmp(*ret_err, "No declaration for attribute xmlns of element MgmtTree\n") == 0) { 1337 free(*ret_err); 1338 debug_print(ctx, 1, "Ignore OMA-DM DDF DTD validation error for MgmtTree namespace declaration with xmlns attribute"); 1339 *ret_err = NULL; 1340 *valid = 1; 1341 } else 1342 *valid = 0; 1343 1344 mo = tnds_to_mo(ctx->xml, tnds); 1345 xml_node_free(ctx->xml, tnds); 1346 if (mo == NULL) { 1347 debug_print(ctx, 1, "invalid moContainer for %s", urn); 1348 } 1349 1350 return mo; 1351 } 1352 1353 1354 static xml_node_t * spp_exec_upload_mo(struct hs20_svc *ctx, 1355 const char *session_id, const char *urn) 1356 { 1357 xml_namespace_t *ns; 1358 xml_node_t *spp_node, *node, *exec_node; 1359 1360 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1361 NULL); 1362 if (spp_node == NULL) 1363 return NULL; 1364 1365 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1366 1367 node = xml_node_create(ctx->xml, exec_node, ns, "uploadMO"); 1368 xml_node_add_attr(ctx->xml, node, ns, "moURN", urn); 1369 1370 return spp_node; 1371 } 1372 1373 1374 static xml_node_t * hs20_subscription_registration(struct hs20_svc *ctx, 1375 const char *realm, 1376 const char *session_id, 1377 const char *redirect_uri, 1378 const u8 *mac_addr) 1379 { 1380 xml_namespace_t *ns; 1381 xml_node_t *spp_node, *exec_node; 1382 char uri[300], *val; 1383 1384 if (db_add_session(ctx, NULL, realm, session_id, NULL, redirect_uri, 1385 SUBSCRIPTION_REGISTRATION, mac_addr) < 0) 1386 return NULL; 1387 val = db_get_osu_config_val(ctx, realm, "signup_url"); 1388 if (val == NULL) 1389 return NULL; 1390 1391 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1392 NULL); 1393 if (spp_node == NULL) 1394 return NULL; 1395 1396 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1397 1398 snprintf(uri, sizeof(uri), "%s%s", val, session_id); 1399 os_free(val); 1400 xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", 1401 uri); 1402 return spp_node; 1403 } 1404 1405 1406 static xml_node_t * hs20_user_input_remediation(struct hs20_svc *ctx, 1407 const char *user, 1408 const char *realm, int dmacc, 1409 const char *session_id) 1410 { 1411 return build_sub_rem_resp(ctx, user, realm, session_id, 0, dmacc); 1412 } 1413 1414 1415 static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, 1416 const char *field) 1417 { 1418 char *cmd; 1419 struct get_db_field_data data; 1420 1421 cmd = sqlite3_mprintf("SELECT value FROM osu_config WHERE realm=%Q AND " 1422 "field=%Q", realm, field); 1423 if (cmd == NULL) 1424 return NULL; 1425 debug_print(ctx, 1, "DB: %s", cmd); 1426 memset(&data, 0, sizeof(data)); 1427 data.field = "value"; 1428 if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) 1429 { 1430 debug_print(ctx, 1, "DB: Could not find osu_config %s: %s", 1431 realm, sqlite3_errmsg(ctx->db)); 1432 sqlite3_free(cmd); 1433 return NULL; 1434 } 1435 sqlite3_free(cmd); 1436 1437 debug_print(ctx, 1, "DB: return '%s'", data.value); 1438 return data.value; 1439 } 1440 1441 1442 static xml_node_t * build_pps(struct hs20_svc *ctx, 1443 const char *user, const char *realm, 1444 const char *pw, const char *cert, 1445 int machine_managed, const char *test, 1446 const char *imsi, const char *dmacc_username, 1447 const char *dmacc_password, 1448 xml_node_t *policy_node) 1449 { 1450 xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp, *p; 1451 xml_node_t *cred, *eap, *userpw; 1452 1453 pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 1454 "PerProviderSubscription"); 1455 if (!pps) { 1456 xml_node_free(ctx->xml, policy_node); 1457 return NULL; 1458 } 1459 1460 add_text_node(ctx, pps, "UpdateIdentifier", "1"); 1461 1462 c = xml_node_create(ctx->xml, pps, NULL, "Cred01"); 1463 1464 add_text_node(ctx, c, "CredentialPriority", "1"); 1465 1466 if (imsi) 1467 goto skip_aaa_trust_root; 1468 aaa = xml_node_create(ctx->xml, c, NULL, "AAAServerTrustRoot"); 1469 aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1"); 1470 add_text_node_conf(ctx, realm, aaa1, "CertURL", 1471 "aaa_trust_root_cert_url"); 1472 if (test && os_strcmp(test, "corrupt_aaa_hash") == 0) { 1473 debug_print(ctx, 1, 1474 "TEST: Corrupt PPS/Cred*/AAAServerTrustRoot/Root*/CertSHA256FingerPrint"); 1475 add_text_node_conf_corrupt(ctx, realm, aaa1, 1476 "CertSHA256Fingerprint", 1477 "aaa_trust_root_cert_fingerprint"); 1478 } else { 1479 add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint", 1480 "aaa_trust_root_cert_fingerprint"); 1481 } 1482 1483 if (test && os_strcmp(test, "corrupt_polupd_hash") == 0) { 1484 debug_print(ctx, 1, 1485 "TEST: Corrupt PPS/Cred*/Policy/PolicyUpdate/Trustroot/CertSHA256FingerPrint"); 1486 p = xml_node_create(ctx->xml, c, NULL, "Policy"); 1487 upd = xml_node_create(ctx->xml, p, NULL, "PolicyUpdate"); 1488 add_text_node(ctx, upd, "UpdateInterval", "30"); 1489 add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated"); 1490 add_text_node(ctx, upd, "Restriction", "Unrestricted"); 1491 add_text_node_conf(ctx, realm, upd, "URI", "policy_url"); 1492 trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); 1493 add_text_node_conf(ctx, realm, trust, "CertURL", 1494 "policy_trust_root_cert_url"); 1495 add_text_node_conf_corrupt(ctx, realm, trust, 1496 "CertSHA256Fingerprint", 1497 "policy_trust_root_cert_fingerprint"); 1498 } 1499 skip_aaa_trust_root: 1500 1501 upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate"); 1502 add_text_node(ctx, upd, "UpdateInterval", "4294967295"); 1503 add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated"); 1504 add_text_node(ctx, upd, "Restriction", "HomeSP"); 1505 add_text_node_conf(ctx, realm, upd, "URI", "spp_http_auth_url"); 1506 trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); 1507 add_text_node_conf(ctx, realm, trust, "CertURL", "trust_root_cert_url"); 1508 if (test && os_strcmp(test, "corrupt_subrem_hash") == 0) { 1509 debug_print(ctx, 1, 1510 "TEST: Corrupt PPS/Cred*/SubscriptionUpdate/Trustroot/CertSHA256FingerPrint"); 1511 add_text_node_conf_corrupt(ctx, realm, trust, 1512 "CertSHA256Fingerprint", 1513 "trust_root_cert_fingerprint"); 1514 } else { 1515 add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint", 1516 "trust_root_cert_fingerprint"); 1517 } 1518 1519 if (dmacc_username && 1520 !build_username_password(ctx, upd, dmacc_username, 1521 dmacc_password)) { 1522 xml_node_free(ctx->xml, pps); 1523 xml_node_free(ctx->xml, policy_node); 1524 return NULL; 1525 } 1526 1527 if (policy_node) 1528 xml_node_add_child(ctx->xml, c, policy_node); 1529 1530 homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP"); 1531 add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name"); 1532 add_text_node_conf(ctx, realm, homesp, "FQDN", "fqdn"); 1533 1534 xml_node_create(ctx->xml, c, NULL, "SubscriptionParameters"); 1535 1536 cred = xml_node_create(ctx->xml, c, NULL, "Credential"); 1537 add_creation_date(ctx, cred); 1538 if (imsi) { 1539 xml_node_t *sim; 1540 const char *type = "18"; /* default to EAP-SIM */ 1541 1542 sim = xml_node_create(ctx->xml, cred, NULL, "SIM"); 1543 add_text_node(ctx, sim, "IMSI", imsi); 1544 if (ctx->eap_method && os_strcmp(ctx->eap_method, "AKA") == 0) 1545 type = "23"; 1546 else if (ctx->eap_method && 1547 os_strcmp(ctx->eap_method, "AKA'") == 0) 1548 type = "50"; 1549 add_text_node(ctx, sim, "EAPType", type); 1550 } else if (cert) { 1551 xml_node_t *dc; 1552 dc = xml_node_create(ctx->xml, cred, NULL, 1553 "DigitalCertificate"); 1554 add_text_node(ctx, dc, "CertificateType", "x509v3"); 1555 add_text_node(ctx, dc, "CertSHA256Fingerprint", cert); 1556 } else { 1557 userpw = build_username_password(ctx, cred, user, pw); 1558 add_text_node(ctx, userpw, "MachineManaged", 1559 machine_managed ? "TRUE" : "FALSE"); 1560 eap = xml_node_create(ctx->xml, userpw, NULL, "EAPMethod"); 1561 add_text_node(ctx, eap, "EAPType", "21"); 1562 add_text_node(ctx, eap, "InnerMethod", "MS-CHAP-V2"); 1563 } 1564 add_text_node(ctx, cred, "Realm", realm); 1565 1566 return pps; 1567 } 1568 1569 1570 static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, 1571 const char *session_id, 1572 const char *user, 1573 const char *realm, 1574 int add_est_user) 1575 { 1576 xml_namespace_t *ns; 1577 xml_node_t *spp_node, *enroll, *exec_node; 1578 char *val; 1579 char password[11]; 1580 char *b64; 1581 1582 if (add_est_user && new_password(password, sizeof(password)) < 0) 1583 return NULL; 1584 1585 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1586 NULL); 1587 if (spp_node == NULL) 1588 return NULL; 1589 1590 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1591 1592 enroll = xml_node_create(ctx->xml, exec_node, ns, "getCertificate"); 1593 xml_node_add_attr(ctx->xml, enroll, NULL, "enrollmentProtocol", "EST"); 1594 1595 val = db_get_osu_config_val(ctx, realm, "est_url"); 1596 xml_node_create_text(ctx->xml, enroll, ns, "enrollmentServerURI", 1597 val ? val : ""); 1598 os_free(val); 1599 1600 if (!add_est_user) 1601 return spp_node; 1602 1603 xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user); 1604 1605 b64 = (char *) base64_encode((unsigned char *) password, 1606 strlen(password), NULL); 1607 if (b64 == NULL) { 1608 xml_node_free(ctx->xml, spp_node); 1609 return NULL; 1610 } 1611 xml_node_create_text(ctx->xml, enroll, ns, "estPassword", b64); 1612 free(b64); 1613 1614 db_update_session_password(ctx, user, realm, session_id, password); 1615 1616 return spp_node; 1617 } 1618 1619 1620 static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx, 1621 const char *session_id, 1622 int enrollment_done) 1623 { 1624 xml_namespace_t *ns; 1625 xml_node_t *spp_node, *node = NULL; 1626 xml_node_t *pps, *tnds; 1627 char buf[400]; 1628 char *str; 1629 char *user, *realm, *pw, *type, *mm, *test; 1630 const char *status; 1631 int cert = 0; 1632 int machine_managed = 0; 1633 char *fingerprint; 1634 1635 user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); 1636 realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); 1637 pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); 1638 1639 if (!user || !realm || !pw) { 1640 debug_print(ctx, 1, "Could not find session info from DB for " 1641 "the new subscription"); 1642 free(user); 1643 free(realm); 1644 free(pw); 1645 return NULL; 1646 } 1647 1648 mm = db_get_session_val(ctx, NULL, NULL, session_id, "machine_managed"); 1649 if (mm && atoi(mm)) 1650 machine_managed = 1; 1651 free(mm); 1652 1653 type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); 1654 if (type && strcmp(type, "cert") == 0) 1655 cert = 1; 1656 free(type); 1657 1658 if (cert && !enrollment_done) { 1659 xml_node_t *ret; 1660 hs20_eventlog(ctx, user, realm, session_id, 1661 "request client certificate enrollment", NULL); 1662 ret = spp_exec_get_certificate(ctx, session_id, user, realm, 1); 1663 free(user); 1664 free(realm); 1665 free(pw); 1666 return ret; 1667 } 1668 1669 if (!cert && strlen(pw) == 0) { 1670 machine_managed = 1; 1671 free(pw); 1672 pw = malloc(11); 1673 if (pw == NULL || new_password(pw, 11) < 0) { 1674 free(user); 1675 free(realm); 1676 free(pw); 1677 return NULL; 1678 } 1679 } 1680 1681 status = "Provisioning complete, request sppUpdateResponse"; 1682 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1683 NULL); 1684 if (spp_node == NULL) 1685 return NULL; 1686 1687 fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); 1688 test = db_get_session_val(ctx, NULL, NULL, session_id, "test"); 1689 if (test) 1690 debug_print(ctx, 1, "TEST: Requested special behavior: %s", 1691 test); 1692 pps = build_pps(ctx, user, realm, pw, 1693 fingerprint ? fingerprint : NULL, machine_managed, 1694 test, NULL, NULL, NULL, NULL); 1695 free(fingerprint); 1696 free(test); 1697 if (!pps) { 1698 xml_node_free(ctx->xml, spp_node); 1699 free(user); 1700 free(realm); 1701 free(pw); 1702 return NULL; 1703 } 1704 1705 debug_print(ctx, 1, "Request DB subscription registration on success " 1706 "notification"); 1707 if (machine_managed) { 1708 db_update_session_password(ctx, user, realm, session_id, pw); 1709 db_update_session_machine_managed(ctx, user, realm, session_id, 1710 machine_managed); 1711 } 1712 db_add_session_pps(ctx, user, realm, session_id, pps); 1713 1714 hs20_eventlog_node(ctx, user, realm, session_id, 1715 "new subscription", pps); 1716 free(user); 1717 free(pw); 1718 1719 tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); 1720 xml_node_free(ctx->xml, pps); 1721 if (!tnds) { 1722 xml_node_free(ctx->xml, spp_node); 1723 free(realm); 1724 return NULL; 1725 } 1726 1727 str = xml_node_to_str(ctx->xml, tnds); 1728 xml_node_free(ctx->xml, tnds); 1729 if (str == NULL) { 1730 xml_node_free(ctx->xml, spp_node); 1731 free(realm); 1732 return NULL; 1733 } 1734 1735 node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); 1736 free(str); 1737 snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); 1738 free(realm); 1739 xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); 1740 xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); 1741 1742 return spp_node; 1743 } 1744 1745 1746 static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx, 1747 const char *user, 1748 const char *realm, 1749 const char *session_id) 1750 { 1751 xml_namespace_t *ns; 1752 xml_node_t *spp_node; 1753 xml_node_t *cred; 1754 char buf[400]; 1755 char *status; 1756 char *free_account, *pw; 1757 1758 free_account = db_get_osu_config_val(ctx, realm, "free_account"); 1759 if (free_account == NULL) 1760 return NULL; 1761 pw = db_get_val(ctx, free_account, realm, "password", 0); 1762 if (pw == NULL) { 1763 free(free_account); 1764 return NULL; 1765 } 1766 1767 cred = build_credential_pw(ctx, free_account, realm, pw, 1); 1768 free(free_account); 1769 free(pw); 1770 if (!cred) { 1771 xml_node_free(ctx->xml, cred); 1772 return NULL; 1773 } 1774 1775 status = "Remediation complete, request sppUpdateResponse"; 1776 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1777 NULL); 1778 if (spp_node == NULL) 1779 return NULL; 1780 1781 snprintf(buf, sizeof(buf), 1782 "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", 1783 realm); 1784 1785 if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { 1786 xml_node_free(ctx->xml, spp_node); 1787 return NULL; 1788 } 1789 1790 hs20_eventlog_node(ctx, user, realm, session_id, 1791 "free/public remediation", cred); 1792 xml_node_free(ctx->xml, cred); 1793 1794 return spp_node; 1795 } 1796 1797 1798 static xml_node_t * hs20_user_input_complete(struct hs20_svc *ctx, 1799 const char *user, 1800 const char *realm, int dmacc, 1801 const char *session_id) 1802 { 1803 char *val; 1804 enum hs20_session_operation oper; 1805 1806 val = db_get_session_val(ctx, user, realm, session_id, "operation"); 1807 if (val == NULL) { 1808 debug_print(ctx, 1, "No session %s found to continue", 1809 session_id); 1810 return NULL; 1811 } 1812 oper = atoi(val); 1813 free(val); 1814 1815 if (oper == USER_REMEDIATION) { 1816 return hs20_user_input_remediation(ctx, user, realm, dmacc, 1817 session_id); 1818 } 1819 1820 if (oper == FREE_REMEDIATION) { 1821 return hs20_user_input_free_remediation(ctx, user, realm, 1822 session_id); 1823 } 1824 1825 if (oper == SUBSCRIPTION_REGISTRATION) { 1826 return hs20_user_input_registration(ctx, session_id, 0); 1827 } 1828 1829 debug_print(ctx, 1, "User session %s not in state for user input " 1830 "completion", session_id); 1831 return NULL; 1832 } 1833 1834 1835 static xml_node_t * hs20_cert_reenroll_complete(struct hs20_svc *ctx, 1836 const char *session_id) 1837 { 1838 char *user, *realm, *cert; 1839 char *status; 1840 xml_namespace_t *ns; 1841 xml_node_t *spp_node, *cred; 1842 char buf[400]; 1843 1844 user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); 1845 realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); 1846 cert = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); 1847 if (!user || !realm || !cert) { 1848 debug_print(ctx, 1, 1849 "Could not find session info from DB for certificate reenrollment"); 1850 free(user); 1851 free(realm); 1852 free(cert); 1853 return NULL; 1854 } 1855 1856 cred = build_credential_cert(ctx, user, realm, cert); 1857 if (!cred) { 1858 debug_print(ctx, 1, "Could not build credential"); 1859 free(user); 1860 free(realm); 1861 free(cert); 1862 return NULL; 1863 } 1864 1865 status = "Remediation complete, request sppUpdateResponse"; 1866 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1867 NULL); 1868 if (spp_node == NULL) { 1869 debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); 1870 free(user); 1871 free(realm); 1872 free(cert); 1873 xml_node_free(ctx->xml, cred); 1874 return NULL; 1875 } 1876 1877 snprintf(buf, sizeof(buf), 1878 "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential", 1879 realm); 1880 1881 if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { 1882 debug_print(ctx, 1, "Could not add update node"); 1883 xml_node_free(ctx->xml, spp_node); 1884 free(user); 1885 free(realm); 1886 free(cert); 1887 return NULL; 1888 } 1889 1890 hs20_eventlog_node(ctx, user, realm, session_id, 1891 "certificate reenrollment", cred); 1892 xml_node_free(ctx->xml, cred); 1893 1894 free(user); 1895 free(realm); 1896 free(cert); 1897 return spp_node; 1898 } 1899 1900 1901 static xml_node_t * hs20_cert_enroll_completed(struct hs20_svc *ctx, 1902 const char *user, 1903 const char *realm, int dmacc, 1904 const char *session_id) 1905 { 1906 char *val; 1907 enum hs20_session_operation oper; 1908 1909 val = db_get_session_val(ctx, NULL, NULL, session_id, "operation"); 1910 if (val == NULL) { 1911 debug_print(ctx, 1, "No session %s found to continue", 1912 session_id); 1913 return NULL; 1914 } 1915 oper = atoi(val); 1916 free(val); 1917 1918 if (oper == SUBSCRIPTION_REGISTRATION) 1919 return hs20_user_input_registration(ctx, session_id, 1); 1920 if (oper == CERT_REENROLL) 1921 return hs20_cert_reenroll_complete(ctx, session_id); 1922 1923 debug_print(ctx, 1, "User session %s not in state for certificate " 1924 "enrollment completion", session_id); 1925 return NULL; 1926 } 1927 1928 1929 static xml_node_t * hs20_cert_enroll_failed(struct hs20_svc *ctx, 1930 const char *user, 1931 const char *realm, int dmacc, 1932 const char *session_id) 1933 { 1934 char *val; 1935 enum hs20_session_operation oper; 1936 xml_node_t *spp_node, *node; 1937 char *status; 1938 xml_namespace_t *ns; 1939 1940 val = db_get_session_val(ctx, user, realm, session_id, "operation"); 1941 if (val == NULL) { 1942 debug_print(ctx, 1, "No session %s found to continue", 1943 session_id); 1944 return NULL; 1945 } 1946 oper = atoi(val); 1947 free(val); 1948 1949 if (oper != SUBSCRIPTION_REGISTRATION) { 1950 debug_print(ctx, 1, "User session %s not in state for " 1951 "enrollment failure", session_id); 1952 return NULL; 1953 } 1954 1955 status = "Error occurred"; 1956 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1957 NULL); 1958 if (spp_node == NULL) 1959 return NULL; 1960 node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); 1961 xml_node_add_attr(ctx->xml, node, NULL, "errorCode", 1962 "Credentials cannot be provisioned at this time"); 1963 db_remove_session(ctx, user, realm, session_id); 1964 1965 return spp_node; 1966 } 1967 1968 1969 static xml_node_t * hs20_sim_provisioning(struct hs20_svc *ctx, 1970 const char *user, 1971 const char *realm, int dmacc, 1972 const char *session_id) 1973 { 1974 xml_namespace_t *ns; 1975 xml_node_t *spp_node, *node = NULL; 1976 xml_node_t *pps, *tnds; 1977 char buf[400]; 1978 char *str; 1979 const char *status; 1980 char dmacc_username[32]; 1981 char dmacc_password[32]; 1982 char *policy; 1983 xml_node_t *policy_node = NULL; 1984 1985 if (!ctx->imsi) { 1986 debug_print(ctx, 1, "IMSI not available for SIM provisioning"); 1987 return NULL; 1988 } 1989 1990 if (new_password(dmacc_username, sizeof(dmacc_username)) < 0 || 1991 new_password(dmacc_password, sizeof(dmacc_password)) < 0) { 1992 debug_print(ctx, 1, 1993 "Failed to generate DMAcc username/password"); 1994 return NULL; 1995 } 1996 1997 status = "Provisioning complete, request sppUpdateResponse"; 1998 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1999 NULL); 2000 if (!spp_node) 2001 return NULL; 2002 2003 policy = db_get_osu_config_val(ctx, realm, "sim_policy"); 2004 if (policy) { 2005 policy_node = read_policy_file(ctx, policy); 2006 os_free(policy); 2007 if (!policy_node) { 2008 xml_node_free(ctx->xml, spp_node); 2009 return NULL; 2010 } 2011 update_policy_update_uri(ctx, realm, policy_node); 2012 node = get_node_uri(ctx->xml, policy_node, 2013 "Policy/PolicyUpdate"); 2014 if (node) 2015 build_username_password(ctx, node, dmacc_username, 2016 dmacc_password); 2017 } 2018 2019 pps = build_pps(ctx, NULL, realm, NULL, NULL, 0, NULL, ctx->imsi, 2020 dmacc_username, dmacc_password, policy_node); 2021 if (!pps) { 2022 xml_node_free(ctx->xml, spp_node); 2023 return NULL; 2024 } 2025 2026 debug_print(ctx, 1, 2027 "Request DB subscription registration on success notification"); 2028 if (!user || !user[0]) 2029 user = ctx->imsi; 2030 db_add_session(ctx, user, realm, session_id, NULL, NULL, 2031 SUBSCRIPTION_REGISTRATION, NULL); 2032 db_add_session_dmacc(ctx, session_id, dmacc_username, dmacc_password); 2033 if (ctx->eap_method) 2034 db_add_session_eap_method(ctx, session_id, ctx->eap_method); 2035 if (ctx->id_hash) 2036 db_add_session_id_hash(ctx, session_id, ctx->id_hash); 2037 db_add_session_pps(ctx, user, realm, session_id, pps); 2038 2039 hs20_eventlog_node(ctx, user, realm, session_id, 2040 "new subscription", pps); 2041 2042 tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); 2043 xml_node_free(ctx->xml, pps); 2044 if (!tnds) { 2045 xml_node_free(ctx->xml, spp_node); 2046 return NULL; 2047 } 2048 2049 str = xml_node_to_str(ctx->xml, tnds); 2050 xml_node_free(ctx->xml, tnds); 2051 if (!str) { 2052 xml_node_free(ctx->xml, spp_node); 2053 return NULL; 2054 } 2055 2056 node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); 2057 free(str); 2058 snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); 2059 xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); 2060 xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); 2061 2062 return spp_node; 2063 } 2064 2065 2066 static xml_node_t * hs20_spp_post_dev_data(struct hs20_svc *ctx, 2067 xml_node_t *node, 2068 const char *user, 2069 const char *realm, 2070 const char *session_id, 2071 int dmacc) 2072 { 2073 const char *req_reason; 2074 char *redirect_uri = NULL; 2075 char *req_reason_buf = NULL; 2076 char str[200]; 2077 xml_node_t *ret = NULL, *devinfo = NULL, *devdetail = NULL; 2078 xml_node_t *mo, *macaddr; 2079 char *version; 2080 int valid; 2081 char *supp, *pos; 2082 char *err; 2083 u8 wifi_mac_addr[ETH_ALEN]; 2084 2085 version = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, 2086 "sppVersion"); 2087 if (version == NULL || strstr(version, "1.0") == NULL) { 2088 ret = build_post_dev_data_response( 2089 ctx, NULL, session_id, "Error occurred", 2090 "SPP version not supported"); 2091 hs20_eventlog_node(ctx, user, realm, session_id, 2092 "Unsupported sppVersion", ret); 2093 xml_node_get_attr_value_free(ctx->xml, version); 2094 return ret; 2095 } 2096 xml_node_get_attr_value_free(ctx->xml, version); 2097 2098 mo = get_node(ctx->xml, node, "supportedMOList"); 2099 if (mo == NULL) { 2100 ret = build_post_dev_data_response( 2101 ctx, NULL, session_id, "Error occurred", 2102 "Other"); 2103 hs20_eventlog_node(ctx, user, realm, session_id, 2104 "No supportedMOList element", ret); 2105 return ret; 2106 } 2107 supp = xml_node_get_text(ctx->xml, mo); 2108 for (pos = supp; pos && *pos; pos++) 2109 *pos = tolower(*pos); 2110 if (supp == NULL || 2111 strstr(supp, URN_OMA_DM_DEVINFO) == NULL || 2112 strstr(supp, URN_OMA_DM_DEVDETAIL) == NULL || 2113 strstr(supp, URN_HS20_PPS) == NULL) { 2114 xml_node_get_text_free(ctx->xml, supp); 2115 ret = build_post_dev_data_response( 2116 ctx, NULL, session_id, "Error occurred", 2117 "One or more mandatory MOs not supported"); 2118 hs20_eventlog_node(ctx, user, realm, session_id, 2119 "Unsupported MOs", ret); 2120 return ret; 2121 } 2122 xml_node_get_text_free(ctx->xml, supp); 2123 2124 req_reason_buf = xml_node_get_attr_value(ctx->xml, node, 2125 "requestReason"); 2126 if (req_reason_buf == NULL) { 2127 debug_print(ctx, 1, "No requestReason attribute"); 2128 return NULL; 2129 } 2130 req_reason = req_reason_buf; 2131 2132 redirect_uri = xml_node_get_attr_value(ctx->xml, node, "redirectURI"); 2133 2134 debug_print(ctx, 1, "requestReason: %s sessionID: %s redirectURI: %s", 2135 req_reason, session_id, redirect_uri); 2136 snprintf(str, sizeof(str), "sppPostDevData: requestReason=%s", 2137 req_reason); 2138 hs20_eventlog(ctx, user, realm, session_id, str, NULL); 2139 2140 devinfo = spp_get_mo(ctx, node, URN_OMA_DM_DEVINFO, &valid, &err); 2141 if (devinfo == NULL) { 2142 ret = build_post_dev_data_response(ctx, NULL, session_id, 2143 "Error occurred", "Other"); 2144 hs20_eventlog_node(ctx, user, realm, session_id, 2145 "No DevInfo moContainer in sppPostDevData", 2146 ret); 2147 os_free(err); 2148 goto out; 2149 } 2150 2151 hs20_eventlog_node(ctx, user, realm, session_id, 2152 "Received DevInfo MO", devinfo); 2153 if (valid == 0) { 2154 hs20_eventlog(ctx, user, realm, session_id, 2155 "OMA-DM DDF DTD validation errors in DevInfo MO", 2156 err); 2157 ret = build_post_dev_data_response(ctx, NULL, session_id, 2158 "Error occurred", "Other"); 2159 os_free(err); 2160 goto out; 2161 } 2162 os_free(err); 2163 if (user) 2164 db_update_mo(ctx, user, realm, "devinfo", devinfo); 2165 2166 devdetail = spp_get_mo(ctx, node, URN_OMA_DM_DEVDETAIL, &valid, &err); 2167 if (devdetail == NULL) { 2168 ret = build_post_dev_data_response(ctx, NULL, session_id, 2169 "Error occurred", "Other"); 2170 hs20_eventlog_node(ctx, user, realm, session_id, 2171 "No DevDetail moContainer in sppPostDevData", 2172 ret); 2173 os_free(err); 2174 goto out; 2175 } 2176 2177 hs20_eventlog_node(ctx, user, realm, session_id, 2178 "Received DevDetail MO", devdetail); 2179 if (valid == 0) { 2180 hs20_eventlog(ctx, user, realm, session_id, 2181 "OMA-DM DDF DTD validation errors " 2182 "in DevDetail MO", err); 2183 ret = build_post_dev_data_response(ctx, NULL, session_id, 2184 "Error occurred", "Other"); 2185 os_free(err); 2186 goto out; 2187 } 2188 os_free(err); 2189 2190 os_memset(wifi_mac_addr, 0, ETH_ALEN); 2191 macaddr = get_node(ctx->xml, devdetail, 2192 "Ext/org.wi-fi/Wi-Fi/Wi-FiMACAddress"); 2193 if (macaddr) { 2194 char *addr, buf[50]; 2195 2196 addr = xml_node_get_text(ctx->xml, macaddr); 2197 if (addr && hwaddr_compact_aton(addr, wifi_mac_addr) == 0) { 2198 snprintf(buf, sizeof(buf), "DevDetail MAC address: " 2199 MACSTR, MAC2STR(wifi_mac_addr)); 2200 hs20_eventlog(ctx, user, realm, session_id, buf, NULL); 2201 xml_node_get_text_free(ctx->xml, addr); 2202 } else { 2203 hs20_eventlog(ctx, user, realm, session_id, 2204 "Could not extract MAC address from DevDetail", 2205 NULL); 2206 } 2207 } else { 2208 hs20_eventlog(ctx, user, realm, session_id, 2209 "No MAC address in DevDetail", NULL); 2210 } 2211 2212 if (user) 2213 db_update_mo(ctx, user, realm, "devdetail", devdetail); 2214 2215 if (user) 2216 mo = spp_get_mo(ctx, node, URN_HS20_PPS, &valid, &err); 2217 else { 2218 mo = NULL; 2219 err = NULL; 2220 } 2221 if (user && mo) { 2222 hs20_eventlog_node(ctx, user, realm, session_id, 2223 "Received PPS MO", mo); 2224 if (valid == 0) { 2225 hs20_eventlog(ctx, user, realm, session_id, 2226 "OMA-DM DDF DTD validation errors " 2227 "in PPS MO", err); 2228 xml_node_get_attr_value_free(ctx->xml, redirect_uri); 2229 os_free(err); 2230 return build_post_dev_data_response( 2231 ctx, NULL, session_id, 2232 "Error occurred", "Other"); 2233 } 2234 db_update_mo(ctx, user, realm, "pps", mo); 2235 db_update_val(ctx, user, realm, "fetch_pps", "0", dmacc); 2236 xml_node_free(ctx->xml, mo); 2237 } 2238 os_free(err); 2239 2240 if (user && !mo) { 2241 char *fetch; 2242 int fetch_pps; 2243 2244 fetch = db_get_val(ctx, user, realm, "fetch_pps", dmacc); 2245 fetch_pps = fetch ? atoi(fetch) : 0; 2246 free(fetch); 2247 2248 if (fetch_pps) { 2249 enum hs20_session_operation oper; 2250 if (strcasecmp(req_reason, "Subscription remediation") 2251 == 0) 2252 oper = CONTINUE_SUBSCRIPTION_REMEDIATION; 2253 else if (strcasecmp(req_reason, "Policy update") == 0) 2254 oper = CONTINUE_POLICY_UPDATE; 2255 else 2256 oper = NO_OPERATION; 2257 if (db_add_session(ctx, user, realm, session_id, NULL, 2258 NULL, oper, NULL) < 0) 2259 goto out; 2260 2261 ret = spp_exec_upload_mo(ctx, session_id, 2262 URN_HS20_PPS); 2263 hs20_eventlog_node(ctx, user, realm, session_id, 2264 "request PPS MO upload", 2265 ret); 2266 goto out; 2267 } 2268 } 2269 2270 if (user && strcasecmp(req_reason, "MO upload") == 0) { 2271 char *val = db_get_session_val(ctx, user, realm, session_id, 2272 "operation"); 2273 enum hs20_session_operation oper; 2274 if (!val) { 2275 debug_print(ctx, 1, "No session %s found to continue", 2276 session_id); 2277 goto out; 2278 } 2279 oper = atoi(val); 2280 free(val); 2281 if (oper == CONTINUE_SUBSCRIPTION_REMEDIATION) 2282 req_reason = "Subscription remediation"; 2283 else if (oper == CONTINUE_POLICY_UPDATE) 2284 req_reason = "Policy update"; 2285 else { 2286 debug_print(ctx, 1, 2287 "No pending operation in session %s", 2288 session_id); 2289 goto out; 2290 } 2291 } 2292 2293 if (strcasecmp(req_reason, "Subscription registration") == 0) { 2294 ret = hs20_subscription_registration(ctx, realm, session_id, 2295 redirect_uri, 2296 wifi_mac_addr); 2297 hs20_eventlog_node(ctx, user, realm, session_id, 2298 "subscription registration response", 2299 ret); 2300 goto out; 2301 } 2302 if (user && strcasecmp(req_reason, "Subscription remediation") == 0) { 2303 ret = hs20_subscription_remediation(ctx, user, realm, 2304 session_id, dmacc, 2305 redirect_uri); 2306 hs20_eventlog_node(ctx, user, realm, session_id, 2307 "subscription remediation response", 2308 ret); 2309 goto out; 2310 } 2311 if (user && strcasecmp(req_reason, "Policy update") == 0) { 2312 ret = hs20_policy_update(ctx, user, realm, session_id, dmacc); 2313 hs20_eventlog_node(ctx, user, realm, session_id, 2314 "policy update response", 2315 ret); 2316 goto out; 2317 } 2318 2319 if (strcasecmp(req_reason, "User input completed") == 0) { 2320 db_add_session_devinfo(ctx, session_id, devinfo); 2321 db_add_session_devdetail(ctx, session_id, devdetail); 2322 ret = hs20_user_input_complete(ctx, user, realm, dmacc, 2323 session_id); 2324 hs20_eventlog_node(ctx, user, realm, session_id, 2325 "user input completed response", ret); 2326 goto out; 2327 } 2328 2329 if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) { 2330 ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc, 2331 session_id); 2332 hs20_eventlog_node(ctx, user, realm, session_id, 2333 "certificate enrollment response", ret); 2334 goto out; 2335 } 2336 2337 if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) { 2338 ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc, 2339 session_id); 2340 hs20_eventlog_node(ctx, user, realm, session_id, 2341 "certificate enrollment failed response", 2342 ret); 2343 goto out; 2344 } 2345 2346 if (strcasecmp(req_reason, "Subscription provisioning") == 0) { 2347 ret = hs20_sim_provisioning(ctx, user, realm, dmacc, 2348 session_id); 2349 hs20_eventlog_node(ctx, user, realm, session_id, 2350 "subscription provisioning response", 2351 ret); 2352 goto out; 2353 } 2354 2355 debug_print(ctx, 1, "Unsupported requestReason '%s' user '%s'", 2356 req_reason, user); 2357 out: 2358 xml_node_get_attr_value_free(ctx->xml, req_reason_buf); 2359 xml_node_get_attr_value_free(ctx->xml, redirect_uri); 2360 if (devinfo) 2361 xml_node_free(ctx->xml, devinfo); 2362 if (devdetail) 2363 xml_node_free(ctx->xml, devdetail); 2364 return ret; 2365 } 2366 2367 2368 static xml_node_t * build_spp_exchange_complete(struct hs20_svc *ctx, 2369 const char *session_id, 2370 const char *status, 2371 const char *error_code) 2372 { 2373 xml_namespace_t *ns; 2374 xml_node_t *spp_node, *node; 2375 2376 spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, 2377 "sppExchangeComplete"); 2378 2379 2380 xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); 2381 xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); 2382 xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); 2383 2384 if (error_code) { 2385 node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); 2386 xml_node_add_attr(ctx->xml, node, NULL, "errorCode", 2387 error_code); 2388 } 2389 2390 return spp_node; 2391 } 2392 2393 2394 static int add_subscription(struct hs20_svc *ctx, const char *session_id) 2395 { 2396 char *user, *realm, *pw, *pw_mm, *pps, *str; 2397 char *osu_user, *osu_password, *eap_method; 2398 char *policy = NULL; 2399 char *sql; 2400 int ret = -1; 2401 char *free_account; 2402 int free_acc; 2403 char *type; 2404 int cert = 0; 2405 char *cert_pem, *fingerprint; 2406 const char *method; 2407 2408 user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); 2409 realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); 2410 pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); 2411 pw_mm = db_get_session_val(ctx, NULL, NULL, session_id, 2412 "machine_managed"); 2413 pps = db_get_session_val(ctx, NULL, NULL, session_id, "pps"); 2414 cert_pem = db_get_session_val(ctx, NULL, NULL, session_id, "cert_pem"); 2415 fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); 2416 type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); 2417 if (type && strcmp(type, "cert") == 0) 2418 cert = 1; 2419 free(type); 2420 osu_user = db_get_session_val(ctx, NULL, NULL, session_id, "osu_user"); 2421 osu_password = db_get_session_val(ctx, NULL, NULL, session_id, 2422 "osu_password"); 2423 eap_method = db_get_session_val(ctx, NULL, NULL, session_id, 2424 "eap_method"); 2425 2426 if (!user || !realm || !pw) { 2427 debug_print(ctx, 1, "Could not find session info from DB for " 2428 "the new subscription"); 2429 goto out; 2430 } 2431 2432 free_account = db_get_osu_config_val(ctx, realm, "free_account"); 2433 free_acc = free_account && strcmp(free_account, user) == 0; 2434 free(free_account); 2435 2436 policy = db_get_osu_config_val(ctx, realm, "sim_policy"); 2437 2438 debug_print(ctx, 1, 2439 "New subscription: user='%s' realm='%s' free_acc=%d", 2440 user, realm, free_acc); 2441 debug_print(ctx, 1, "New subscription: pps='%s'", pps); 2442 2443 sql = sqlite3_mprintf("UPDATE eventlog SET user=%Q, realm=%Q WHERE " 2444 "sessionid=%Q AND (user='' OR user IS NULL)", 2445 user, realm, session_id); 2446 if (sql) { 2447 debug_print(ctx, 1, "DB: %s", sql); 2448 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 2449 debug_print(ctx, 1, "Failed to update eventlog in " 2450 "sqlite database: %s", 2451 sqlite3_errmsg(ctx->db)); 2452 } 2453 sqlite3_free(sql); 2454 } 2455 2456 if (free_acc) { 2457 hs20_eventlog(ctx, user, realm, session_id, 2458 "completed shared free account registration", 2459 NULL); 2460 ret = 0; 2461 goto out; 2462 } 2463 2464 str = db_get_session_val(ctx, NULL, NULL, session_id, "mac_addr"); 2465 2466 if (eap_method && eap_method[0]) 2467 method = eap_method; 2468 else 2469 method = cert ? "TLS" : "TTLS-MSCHAPV2"; 2470 sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2,methods,cert,cert_pem,machine_managed,mac_addr,osu_user,osu_password,policy) VALUES (%Q,%Q,%d,%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)", 2471 user, realm, cert ? 0 : 1, 2472 method, 2473 fingerprint ? fingerprint : "", 2474 cert_pem ? cert_pem : "", 2475 pw_mm && atoi(pw_mm) ? 1 : 0, 2476 str ? str : "", 2477 osu_user ? osu_user : "", 2478 osu_password ? osu_password : "", 2479 policy ? policy : ""); 2480 free(str); 2481 if (sql == NULL) 2482 goto out; 2483 debug_print(ctx, 1, "DB: %s", sql); 2484 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 2485 debug_print(ctx, 1, "Failed to add user in sqlite database: %s", 2486 sqlite3_errmsg(ctx->db)); 2487 sqlite3_free(sql); 2488 goto out; 2489 } 2490 sqlite3_free(sql); 2491 2492 if (cert) 2493 ret = 0; 2494 else 2495 ret = update_password(ctx, user, realm, pw, 0); 2496 if (ret < 0) { 2497 sql = sqlite3_mprintf("DELETE FROM users WHERE identity=%Q AND realm=%Q AND (phase2=1 OR methods='TLS')", 2498 user, realm); 2499 if (sql) { 2500 debug_print(ctx, 1, "DB: %s", sql); 2501 sqlite3_exec(ctx->db, sql, NULL, NULL, NULL); 2502 sqlite3_free(sql); 2503 } 2504 } 2505 2506 if (pps) 2507 db_update_mo_str(ctx, user, realm, "pps", pps); 2508 2509 str = db_get_session_val(ctx, NULL, NULL, session_id, "devinfo"); 2510 if (str) { 2511 db_update_mo_str(ctx, user, realm, "devinfo", str); 2512 free(str); 2513 } 2514 2515 str = db_get_session_val(ctx, NULL, NULL, session_id, "devdetail"); 2516 if (str) { 2517 db_update_mo_str(ctx, user, realm, "devdetail", str); 2518 free(str); 2519 } 2520 2521 if (cert && user) { 2522 const char *serialnum; 2523 2524 str = db_get_session_val(ctx, NULL, NULL, session_id, 2525 "mac_addr"); 2526 2527 if (os_strncmp(user, "cert-", 5) == 0) 2528 serialnum = user + 5; 2529 else 2530 serialnum = ""; 2531 sql = sqlite3_mprintf("INSERT OR REPLACE INTO cert_enroll (mac_addr,user,realm,serialnum) VALUES(%Q,%Q,%Q,%Q)", 2532 str ? str : "", user, realm ? realm : "", 2533 serialnum); 2534 free(str); 2535 if (sql) { 2536 debug_print(ctx, 1, "DB: %s", sql); 2537 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != 2538 SQLITE_OK) { 2539 debug_print(ctx, 1, 2540 "Failed to add cert_enroll entry into sqlite database: %s", 2541 sqlite3_errmsg(ctx->db)); 2542 } 2543 sqlite3_free(sql); 2544 } 2545 } 2546 2547 str = db_get_session_val(ctx, NULL, NULL, session_id, 2548 "mobile_identifier_hash"); 2549 if (str) { 2550 sql = sqlite3_mprintf("DELETE FROM sim_provisioning WHERE mobile_identifier_hash=%Q", 2551 str); 2552 if (sql) { 2553 debug_print(ctx, 1, "DB: %s", sql); 2554 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != 2555 SQLITE_OK) { 2556 debug_print(ctx, 1, 2557 "Failed to delete pending sim_provisioning entry: %s", 2558 sqlite3_errmsg(ctx->db)); 2559 } 2560 sqlite3_free(sql); 2561 } 2562 os_free(str); 2563 } 2564 2565 if (ret == 0) { 2566 hs20_eventlog(ctx, user, realm, session_id, 2567 "completed subscription registration", NULL); 2568 } 2569 2570 out: 2571 free(user); 2572 free(realm); 2573 free(pw); 2574 free(pw_mm); 2575 free(pps); 2576 free(cert_pem); 2577 free(fingerprint); 2578 free(osu_user); 2579 free(osu_password); 2580 free(eap_method); 2581 os_free(policy); 2582 return ret; 2583 } 2584 2585 2586 static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx, 2587 xml_node_t *node, 2588 const char *user, 2589 const char *realm, 2590 const char *session_id, 2591 int dmacc) 2592 { 2593 char *status; 2594 xml_node_t *ret; 2595 char *val; 2596 enum hs20_session_operation oper; 2597 2598 status = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, 2599 "sppStatus"); 2600 if (status == NULL) { 2601 debug_print(ctx, 1, "No sppStatus attribute"); 2602 return NULL; 2603 } 2604 2605 debug_print(ctx, 1, "sppUpdateResponse: sppStatus: %s sessionID: %s", 2606 status, session_id); 2607 2608 val = db_get_session_val(ctx, NULL, NULL, session_id, "operation"); 2609 if (!val) { 2610 debug_print(ctx, 1, 2611 "No session active for sessionID: %s", 2612 session_id); 2613 oper = NO_OPERATION; 2614 } else 2615 oper = atoi(val); 2616 2617 if (strcasecmp(status, "OK") == 0) { 2618 char *new_pw = NULL; 2619 2620 xml_node_get_attr_value_free(ctx->xml, status); 2621 2622 if (oper == USER_REMEDIATION) { 2623 new_pw = db_get_session_val(ctx, user, realm, 2624 session_id, "password"); 2625 if (new_pw == NULL || strlen(new_pw) == 0) { 2626 free(new_pw); 2627 ret = build_spp_exchange_complete( 2628 ctx, session_id, "Error occurred", 2629 "Other"); 2630 hs20_eventlog_node(ctx, user, realm, 2631 session_id, "No password " 2632 "had been assigned for " 2633 "session", ret); 2634 db_remove_session(ctx, user, realm, session_id); 2635 return ret; 2636 } 2637 oper = UPDATE_PASSWORD; 2638 } 2639 if (oper == UPDATE_PASSWORD) { 2640 if (!new_pw) { 2641 new_pw = db_get_session_val(ctx, user, realm, 2642 session_id, 2643 "password"); 2644 if (!new_pw) { 2645 db_remove_session(ctx, user, realm, 2646 session_id); 2647 return NULL; 2648 } 2649 } 2650 debug_print(ctx, 1, "Update user '%s' password in DB", 2651 user); 2652 if (update_password(ctx, user, realm, new_pw, dmacc) < 2653 0) { 2654 debug_print(ctx, 1, "Failed to update user " 2655 "'%s' password in DB", user); 2656 ret = build_spp_exchange_complete( 2657 ctx, session_id, "Error occurred", 2658 "Other"); 2659 hs20_eventlog_node(ctx, user, realm, 2660 session_id, "Failed to " 2661 "update database", ret); 2662 db_remove_session(ctx, user, realm, session_id); 2663 return ret; 2664 } 2665 hs20_eventlog(ctx, user, realm, 2666 session_id, "Updated user password " 2667 "in database", NULL); 2668 } 2669 if (oper == CLEAR_REMEDIATION) { 2670 debug_print(ctx, 1, 2671 "Clear remediation requirement for user '%s' in DB", 2672 user); 2673 if (clear_remediation(ctx, user, realm, dmacc) < 0) { 2674 debug_print(ctx, 1, 2675 "Failed to clear remediation requirement for user '%s' in DB", 2676 user); 2677 ret = build_spp_exchange_complete( 2678 ctx, session_id, "Error occurred", 2679 "Other"); 2680 hs20_eventlog_node(ctx, user, realm, 2681 session_id, 2682 "Failed to update database", 2683 ret); 2684 db_remove_session(ctx, user, realm, session_id); 2685 return ret; 2686 } 2687 hs20_eventlog(ctx, user, realm, 2688 session_id, 2689 "Cleared remediation requirement in database", 2690 NULL); 2691 } 2692 if (oper == SUBSCRIPTION_REGISTRATION) { 2693 if (add_subscription(ctx, session_id) < 0) { 2694 debug_print(ctx, 1, "Failed to add " 2695 "subscription into DB"); 2696 ret = build_spp_exchange_complete( 2697 ctx, session_id, "Error occurred", 2698 "Other"); 2699 hs20_eventlog_node(ctx, user, realm, 2700 session_id, "Failed to " 2701 "update database", ret); 2702 db_remove_session(ctx, user, realm, session_id); 2703 return ret; 2704 } 2705 } 2706 if (oper == POLICY_REMEDIATION || oper == POLICY_UPDATE) { 2707 char *val; 2708 val = db_get_val(ctx, user, realm, "remediation", 2709 dmacc); 2710 if (val && strcmp(val, "policy") == 0) 2711 db_update_val(ctx, user, realm, "remediation", 2712 "", dmacc); 2713 free(val); 2714 } 2715 if (oper == POLICY_UPDATE) 2716 db_update_val(ctx, user, realm, "polupd_done", "1", 2717 dmacc); 2718 if (oper == CERT_REENROLL) { 2719 char *new_user; 2720 char event[200]; 2721 2722 new_user = db_get_session_val(ctx, NULL, NULL, 2723 session_id, "user"); 2724 if (!new_user) { 2725 debug_print(ctx, 1, 2726 "Failed to find new user name (cert-serialnum)"); 2727 ret = build_spp_exchange_complete( 2728 ctx, session_id, "Error occurred", 2729 "Other"); 2730 hs20_eventlog_node(ctx, user, realm, 2731 session_id, 2732 "Failed to find new user name (cert reenroll)", 2733 ret); 2734 db_remove_session(ctx, NULL, NULL, session_id); 2735 return ret; 2736 } 2737 2738 debug_print(ctx, 1, 2739 "Update certificate user entry to use the new serial number (old=%s new=%s)", 2740 user, new_user); 2741 os_snprintf(event, sizeof(event), "renamed user to: %s", 2742 new_user); 2743 hs20_eventlog(ctx, user, realm, session_id, event, 2744 NULL); 2745 2746 if (db_update_val(ctx, user, realm, "identity", 2747 new_user, 0) < 0 || 2748 db_update_val(ctx, new_user, realm, "remediation", 2749 "", 0) < 0) { 2750 debug_print(ctx, 1, 2751 "Failed to update user name (cert-serialnum)"); 2752 ret = build_spp_exchange_complete( 2753 ctx, session_id, "Error occurred", 2754 "Other"); 2755 hs20_eventlog_node(ctx, user, realm, 2756 session_id, 2757 "Failed to update user name (cert reenroll)", 2758 ret); 2759 db_remove_session(ctx, NULL, NULL, session_id); 2760 os_free(new_user); 2761 return ret; 2762 } 2763 2764 os_free(new_user); 2765 } 2766 ret = build_spp_exchange_complete( 2767 ctx, session_id, 2768 "Exchange complete, release TLS connection", NULL); 2769 hs20_eventlog_node(ctx, user, realm, session_id, 2770 "Exchange completed", ret); 2771 db_remove_session(ctx, NULL, NULL, session_id); 2772 return ret; 2773 } 2774 2775 ret = build_spp_exchange_complete(ctx, session_id, "Error occurred", 2776 "Other"); 2777 hs20_eventlog_node(ctx, user, realm, session_id, "Error occurred", ret); 2778 db_remove_session(ctx, user, realm, session_id); 2779 xml_node_get_attr_value_free(ctx->xml, status); 2780 return ret; 2781 } 2782 2783 2784 #define SPP_SESSION_ID_LEN 16 2785 2786 static char * gen_spp_session_id(void) 2787 { 2788 FILE *f; 2789 int i; 2790 char *session; 2791 2792 session = os_malloc(SPP_SESSION_ID_LEN * 2 + 1); 2793 if (session == NULL) 2794 return NULL; 2795 2796 f = fopen("/dev/urandom", "r"); 2797 if (f == NULL) { 2798 os_free(session); 2799 return NULL; 2800 } 2801 for (i = 0; i < SPP_SESSION_ID_LEN; i++) 2802 os_snprintf(session + i * 2, 3, "%02x", fgetc(f)); 2803 2804 fclose(f); 2805 return session; 2806 } 2807 2808 xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node, 2809 const char *auth_user, 2810 const char *auth_realm, int dmacc) 2811 { 2812 xml_node_t *ret = NULL; 2813 char *session_id; 2814 const char *op_name; 2815 char *xml_err; 2816 char fname[200]; 2817 2818 debug_dump_node(ctx, "received request", node); 2819 2820 if (!dmacc && auth_user && auth_realm) { 2821 char *real; 2822 real = db_get_val(ctx, auth_user, auth_realm, "identity", 0); 2823 if (!real) { 2824 real = db_get_val(ctx, auth_user, auth_realm, 2825 "identity", 1); 2826 if (real) 2827 dmacc = 1; 2828 } 2829 os_free(real); 2830 } 2831 2832 snprintf(fname, sizeof(fname), "%s/spp/spp.xsd", ctx->root_dir); 2833 if (xml_validate(ctx->xml, node, fname, &xml_err) < 0) { 2834 /* 2835 * We may not be able to extract the sessionID from invalid 2836 * input, but well, we can try. 2837 */ 2838 session_id = xml_node_get_attr_value_ns(ctx->xml, node, 2839 SPP_NS_URI, 2840 "sessionID"); 2841 debug_print(ctx, 1, 2842 "SPP message failed validation, xsd file: %s xml-error: %s", 2843 fname, xml_err); 2844 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2845 "SPP message failed validation", node); 2846 hs20_eventlog(ctx, auth_user, auth_realm, session_id, 2847 "Validation errors", xml_err); 2848 os_free(xml_err); 2849 xml_node_get_attr_value_free(ctx->xml, session_id); 2850 /* TODO: what to return here? */ 2851 ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 2852 "SppValidationError"); 2853 return ret; 2854 } 2855 2856 session_id = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, 2857 "sessionID"); 2858 if (session_id) { 2859 char *tmp; 2860 debug_print(ctx, 1, "Received sessionID %s", session_id); 2861 tmp = os_strdup(session_id); 2862 xml_node_get_attr_value_free(ctx->xml, session_id); 2863 if (tmp == NULL) 2864 return NULL; 2865 session_id = tmp; 2866 } else { 2867 session_id = gen_spp_session_id(); 2868 if (session_id == NULL) { 2869 debug_print(ctx, 1, "Failed to generate sessionID"); 2870 return NULL; 2871 } 2872 debug_print(ctx, 1, "Generated sessionID %s", session_id); 2873 } 2874 2875 op_name = xml_node_get_localname(ctx->xml, node); 2876 if (op_name == NULL) { 2877 debug_print(ctx, 1, "Could not get op_name"); 2878 return NULL; 2879 } 2880 2881 if (strcmp(op_name, "sppPostDevData") == 0) { 2882 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2883 "sppPostDevData received and validated", 2884 node); 2885 ret = hs20_spp_post_dev_data(ctx, node, auth_user, auth_realm, 2886 session_id, dmacc); 2887 } else if (strcmp(op_name, "sppUpdateResponse") == 0) { 2888 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2889 "sppUpdateResponse received and validated", 2890 node); 2891 ret = hs20_spp_update_response(ctx, node, auth_user, 2892 auth_realm, session_id, dmacc); 2893 } else { 2894 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2895 "Unsupported SPP message received and " 2896 "validated", node); 2897 debug_print(ctx, 1, "Unsupported operation '%s'", op_name); 2898 /* TODO: what to return here? */ 2899 ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 2900 "SppUnknownCommandError"); 2901 } 2902 os_free(session_id); 2903 2904 if (ret == NULL) { 2905 /* TODO: what to return here? */ 2906 ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 2907 "SppInternalError"); 2908 } 2909 2910 return ret; 2911 } 2912 2913 2914 int hs20_spp_server_init(struct hs20_svc *ctx) 2915 { 2916 char fname[200]; 2917 ctx->db = NULL; 2918 snprintf(fname, sizeof(fname), "%s/AS/DB/eap_user.db", ctx->root_dir); 2919 if (sqlite3_open(fname, &ctx->db)) { 2920 printf("Failed to open sqlite database: %s\n", 2921 sqlite3_errmsg(ctx->db)); 2922 sqlite3_close(ctx->db); 2923 return -1; 2924 } 2925 2926 return 0; 2927 } 2928 2929 2930 void hs20_spp_server_deinit(struct hs20_svc *ctx) 2931 { 2932 sqlite3_close(ctx->db); 2933 ctx->db = NULL; 2934 } 2935