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 }; 45 46 47 static char * db_get_session_val(struct hs20_svc *ctx, const char *user, 48 const char *realm, const char *session_id, 49 const char *field); 50 static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, 51 const char *field); 52 static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, 53 const char *realm, int use_dmacc); 54 55 56 static int db_add_session(struct hs20_svc *ctx, 57 const char *user, const char *realm, 58 const char *sessionid, const char *pw, 59 const char *redirect_uri, 60 enum hs20_session_operation operation) 61 { 62 char *sql; 63 int ret = 0; 64 65 sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm," 66 "operation,password,redirect_uri) " 67 "VALUES " 68 "(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," 69 "%Q,%Q,%Q,%d,%Q,%Q)", 70 sessionid, user ? user : "", realm ? realm : "", 71 operation, pw ? pw : "", 72 redirect_uri ? redirect_uri : ""); 73 if (sql == NULL) 74 return -1; 75 debug_print(ctx, 1, "DB: %s", sql); 76 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 77 debug_print(ctx, 1, "Failed to add session entry into sqlite " 78 "database: %s", sqlite3_errmsg(ctx->db)); 79 ret = -1; 80 } 81 sqlite3_free(sql); 82 return ret; 83 } 84 85 86 static void db_update_session_password(struct hs20_svc *ctx, const char *user, 87 const char *realm, const char *sessionid, 88 const char *pw) 89 { 90 char *sql; 91 92 sql = sqlite3_mprintf("UPDATE sessions SET password=%Q WHERE id=%Q AND " 93 "user=%Q AND realm=%Q", 94 pw, sessionid, user, realm); 95 if (sql == NULL) 96 return; 97 debug_print(ctx, 1, "DB: %s", sql); 98 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 99 debug_print(ctx, 1, "Failed to update session password: %s", 100 sqlite3_errmsg(ctx->db)); 101 } 102 sqlite3_free(sql); 103 } 104 105 106 static void db_update_session_machine_managed(struct hs20_svc *ctx, 107 const char *user, 108 const char *realm, 109 const char *sessionid, 110 const int pw_mm) 111 { 112 char *sql; 113 114 sql = sqlite3_mprintf("UPDATE sessions SET machine_managed=%Q WHERE id=%Q AND user=%Q AND realm=%Q", 115 pw_mm ? "1" : "0", sessionid, user, realm); 116 if (sql == NULL) 117 return; 118 debug_print(ctx, 1, "DB: %s", sql); 119 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 120 debug_print(ctx, 1, 121 "Failed to update session machine_managed: %s", 122 sqlite3_errmsg(ctx->db)); 123 } 124 sqlite3_free(sql); 125 } 126 127 128 static void db_add_session_pps(struct hs20_svc *ctx, const char *user, 129 const char *realm, const char *sessionid, 130 xml_node_t *node) 131 { 132 char *str; 133 char *sql; 134 135 str = xml_node_to_str(ctx->xml, node); 136 if (str == NULL) 137 return; 138 sql = sqlite3_mprintf("UPDATE sessions SET pps=%Q WHERE id=%Q AND " 139 "user=%Q AND realm=%Q", 140 str, sessionid, user, realm); 141 free(str); 142 if (sql == NULL) 143 return; 144 debug_print(ctx, 1, "DB: %s", sql); 145 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 146 debug_print(ctx, 1, "Failed to add session pps: %s", 147 sqlite3_errmsg(ctx->db)); 148 } 149 sqlite3_free(sql); 150 } 151 152 153 static void db_add_session_devinfo(struct hs20_svc *ctx, const char *sessionid, 154 xml_node_t *node) 155 { 156 char *str; 157 char *sql; 158 159 str = xml_node_to_str(ctx->xml, node); 160 if (str == NULL) 161 return; 162 sql = sqlite3_mprintf("UPDATE sessions SET devinfo=%Q WHERE id=%Q", 163 str, sessionid); 164 free(str); 165 if (sql == NULL) 166 return; 167 debug_print(ctx, 1, "DB: %s", sql); 168 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 169 debug_print(ctx, 1, "Failed to add session devinfo: %s", 170 sqlite3_errmsg(ctx->db)); 171 } 172 sqlite3_free(sql); 173 } 174 175 176 static void db_add_session_devdetail(struct hs20_svc *ctx, 177 const char *sessionid, 178 xml_node_t *node) 179 { 180 char *str; 181 char *sql; 182 183 str = xml_node_to_str(ctx->xml, node); 184 if (str == NULL) 185 return; 186 sql = sqlite3_mprintf("UPDATE sessions SET devdetail=%Q WHERE id=%Q", 187 str, sessionid); 188 free(str); 189 if (sql == NULL) 190 return; 191 debug_print(ctx, 1, "DB: %s", sql); 192 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 193 debug_print(ctx, 1, "Failed to add session devdetail: %s", 194 sqlite3_errmsg(ctx->db)); 195 } 196 sqlite3_free(sql); 197 } 198 199 200 static void db_remove_session(struct hs20_svc *ctx, 201 const char *user, const char *realm, 202 const char *sessionid) 203 { 204 char *sql; 205 206 if (user == NULL || realm == NULL) { 207 sql = sqlite3_mprintf("DELETE FROM sessions WHERE " 208 "id=%Q", sessionid); 209 } else { 210 sql = sqlite3_mprintf("DELETE FROM sessions WHERE " 211 "user=%Q AND realm=%Q AND id=%Q", 212 user, realm, sessionid); 213 } 214 if (sql == NULL) 215 return; 216 debug_print(ctx, 1, "DB: %s", sql); 217 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 218 debug_print(ctx, 1, "Failed to delete session entry from " 219 "sqlite database: %s", sqlite3_errmsg(ctx->db)); 220 } 221 sqlite3_free(sql); 222 } 223 224 225 static void hs20_eventlog(struct hs20_svc *ctx, 226 const char *user, const char *realm, 227 const char *sessionid, const char *notes, 228 const char *dump) 229 { 230 char *sql; 231 char *user_buf = NULL, *realm_buf = NULL; 232 233 debug_print(ctx, 1, "eventlog: %s", notes); 234 235 if (user == NULL) { 236 user_buf = db_get_session_val(ctx, NULL, NULL, sessionid, 237 "user"); 238 user = user_buf; 239 realm_buf = db_get_session_val(ctx, NULL, NULL, sessionid, 240 "realm"); 241 realm = realm_buf; 242 } 243 244 sql = sqlite3_mprintf("INSERT INTO eventlog" 245 "(user,realm,sessionid,timestamp,notes,dump,addr)" 246 " VALUES (%Q,%Q,%Q," 247 "strftime('%%Y-%%m-%%d %%H:%%M:%%f','now')," 248 "%Q,%Q,%Q)", 249 user, realm, sessionid, notes, 250 dump ? dump : "", ctx->addr ? ctx->addr : ""); 251 free(user_buf); 252 free(realm_buf); 253 if (sql == NULL) 254 return; 255 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 256 debug_print(ctx, 1, "Failed to add eventlog entry into sqlite " 257 "database: %s", sqlite3_errmsg(ctx->db)); 258 } 259 sqlite3_free(sql); 260 } 261 262 263 static void hs20_eventlog_node(struct hs20_svc *ctx, 264 const char *user, const char *realm, 265 const char *sessionid, const char *notes, 266 xml_node_t *node) 267 { 268 char *str; 269 270 if (node) 271 str = xml_node_to_str(ctx->xml, node); 272 else 273 str = NULL; 274 hs20_eventlog(ctx, user, realm, sessionid, notes, str); 275 free(str); 276 } 277 278 279 static void db_update_mo_str(struct hs20_svc *ctx, const char *user, 280 const char *realm, const char *name, 281 const char *str) 282 { 283 char *sql; 284 if (user == NULL || realm == NULL || name == NULL) 285 return; 286 sql = sqlite3_mprintf("UPDATE users SET %s=%Q " 287 "WHERE identity=%Q AND realm=%Q AND phase2=1", 288 name, str, user, realm); 289 if (sql == NULL) 290 return; 291 debug_print(ctx, 1, "DB: %s", sql); 292 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 293 debug_print(ctx, 1, "Failed to update user MO entry in sqlite " 294 "database: %s", sqlite3_errmsg(ctx->db)); 295 } 296 sqlite3_free(sql); 297 } 298 299 300 static void db_update_mo(struct hs20_svc *ctx, const char *user, 301 const char *realm, const char *name, xml_node_t *mo) 302 { 303 char *str; 304 305 str = xml_node_to_str(ctx->xml, mo); 306 if (str == NULL) 307 return; 308 309 db_update_mo_str(ctx, user, realm, name, str); 310 free(str); 311 } 312 313 314 static void add_text_node(struct hs20_svc *ctx, xml_node_t *parent, 315 const char *name, const char *value) 316 { 317 xml_node_create_text(ctx->xml, parent, NULL, name, value ? value : ""); 318 } 319 320 321 static void add_text_node_conf(struct hs20_svc *ctx, const char *realm, 322 xml_node_t *parent, const char *name, 323 const char *field) 324 { 325 char *val; 326 val = db_get_osu_config_val(ctx, realm, field); 327 xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : ""); 328 os_free(val); 329 } 330 331 332 static int new_password(char *buf, int buflen) 333 { 334 int i; 335 336 if (buflen < 1) 337 return -1; 338 buf[buflen - 1] = '\0'; 339 if (os_get_random((unsigned char *) buf, buflen - 1) < 0) 340 return -1; 341 342 for (i = 0; i < buflen - 1; i++) { 343 unsigned char val = buf[i]; 344 val %= 2 * 26 + 10; 345 if (val < 26) 346 buf[i] = 'a' + val; 347 else if (val < 2 * 26) 348 buf[i] = 'A' + val - 26; 349 else 350 buf[i] = '0' + val - 2 * 26; 351 } 352 353 return 0; 354 } 355 356 357 struct get_db_field_data { 358 const char *field; 359 char *value; 360 }; 361 362 363 static int get_db_field(void *ctx, int argc, char *argv[], char *col[]) 364 { 365 struct get_db_field_data *data = ctx; 366 int i; 367 368 for (i = 0; i < argc; i++) { 369 if (os_strcmp(col[i], data->field) == 0 && argv[i]) { 370 os_free(data->value); 371 data->value = os_strdup(argv[i]); 372 break; 373 } 374 } 375 376 return 0; 377 } 378 379 380 static char * db_get_val(struct hs20_svc *ctx, const char *user, 381 const char *realm, const char *field, int dmacc) 382 { 383 char *cmd; 384 struct get_db_field_data data; 385 386 cmd = sqlite3_mprintf("SELECT %s FROM users WHERE " 387 "%s=%Q AND realm=%Q AND phase2=1", 388 field, dmacc ? "osu_user" : "identity", 389 user, realm); 390 if (cmd == NULL) 391 return NULL; 392 memset(&data, 0, sizeof(data)); 393 data.field = field; 394 if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) 395 { 396 debug_print(ctx, 1, "Could not find user '%s'", user); 397 sqlite3_free(cmd); 398 return NULL; 399 } 400 sqlite3_free(cmd); 401 402 debug_print(ctx, 1, "DB: user='%s' realm='%s' field='%s' dmacc=%d --> " 403 "value='%s'", user, realm, field, dmacc, data.value); 404 405 return data.value; 406 } 407 408 409 static int db_update_val(struct hs20_svc *ctx, const char *user, 410 const char *realm, const char *field, 411 const char *val, int dmacc) 412 { 413 char *cmd; 414 int ret; 415 416 cmd = sqlite3_mprintf("UPDATE users SET %s=%Q WHERE " 417 "%s=%Q AND realm=%Q AND phase2=1", 418 field, val, dmacc ? "osu_user" : "identity", user, 419 realm); 420 if (cmd == NULL) 421 return -1; 422 debug_print(ctx, 1, "DB: %s", cmd); 423 if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { 424 debug_print(ctx, 1, 425 "Failed to update user in sqlite database: %s", 426 sqlite3_errmsg(ctx->db)); 427 ret = -1; 428 } else { 429 debug_print(ctx, 1, 430 "DB: user='%s' realm='%s' field='%s' set to '%s'", 431 user, realm, field, val); 432 ret = 0; 433 } 434 sqlite3_free(cmd); 435 436 return ret; 437 } 438 439 440 static char * db_get_session_val(struct hs20_svc *ctx, const char *user, 441 const char *realm, const char *session_id, 442 const char *field) 443 { 444 char *cmd; 445 struct get_db_field_data data; 446 447 if (user == NULL || realm == NULL) { 448 cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " 449 "id=%Q", field, session_id); 450 } else { 451 cmd = sqlite3_mprintf("SELECT %s FROM sessions WHERE " 452 "user=%Q AND realm=%Q AND id=%Q", 453 field, user, realm, session_id); 454 } 455 if (cmd == NULL) 456 return NULL; 457 debug_print(ctx, 1, "DB: %s", cmd); 458 memset(&data, 0, sizeof(data)); 459 data.field = field; 460 if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) 461 { 462 debug_print(ctx, 1, "DB: Could not find session %s: %s", 463 session_id, sqlite3_errmsg(ctx->db)); 464 sqlite3_free(cmd); 465 return NULL; 466 } 467 sqlite3_free(cmd); 468 469 debug_print(ctx, 1, "DB: return '%s'", data.value); 470 return data.value; 471 } 472 473 474 static int update_password(struct hs20_svc *ctx, const char *user, 475 const char *realm, const char *pw, int dmacc) 476 { 477 char *cmd; 478 479 cmd = sqlite3_mprintf("UPDATE users SET password=%Q, " 480 "remediation='' " 481 "WHERE %s=%Q AND phase2=1", 482 pw, dmacc ? "osu_user" : "identity", 483 user); 484 if (cmd == NULL) 485 return -1; 486 debug_print(ctx, 1, "DB: %s", cmd); 487 if (sqlite3_exec(ctx->db, cmd, NULL, NULL, NULL) != SQLITE_OK) { 488 debug_print(ctx, 1, "Failed to update database for user '%s'", 489 user); 490 } 491 sqlite3_free(cmd); 492 493 return 0; 494 } 495 496 497 static int add_eap_ttls(struct hs20_svc *ctx, xml_node_t *parent) 498 { 499 xml_node_t *node; 500 501 node = xml_node_create(ctx->xml, parent, NULL, "EAPMethod"); 502 if (node == NULL) 503 return -1; 504 505 add_text_node(ctx, node, "EAPType", "21"); 506 add_text_node(ctx, node, "InnerMethod", "MS-CHAP-V2"); 507 508 return 0; 509 } 510 511 512 static xml_node_t * build_username_password(struct hs20_svc *ctx, 513 xml_node_t *parent, 514 const char *user, const char *pw) 515 { 516 xml_node_t *node; 517 char *b64; 518 519 node = xml_node_create(ctx->xml, parent, NULL, "UsernamePassword"); 520 if (node == NULL) 521 return NULL; 522 523 add_text_node(ctx, node, "Username", user); 524 525 b64 = (char *) base64_encode((unsigned char *) pw, strlen(pw), NULL); 526 if (b64 == NULL) 527 return NULL; 528 add_text_node(ctx, node, "Password", b64); 529 free(b64); 530 531 return node; 532 } 533 534 535 static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred, 536 const char *user, const char *pw) 537 { 538 xml_node_t *node; 539 540 node = build_username_password(ctx, cred, user, pw); 541 if (node == NULL) 542 return -1; 543 544 add_text_node(ctx, node, "MachineManaged", "TRUE"); 545 add_text_node(ctx, node, "SoftTokenApp", ""); 546 add_eap_ttls(ctx, node); 547 548 return 0; 549 } 550 551 552 static void add_creation_date(struct hs20_svc *ctx, xml_node_t *cred) 553 { 554 char str[30]; 555 time_t now; 556 struct tm tm; 557 558 time(&now); 559 gmtime_r(&now, &tm); 560 snprintf(str, sizeof(str), "%04u-%02u-%02uT%02u:%02u:%02uZ", 561 tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 562 tm.tm_hour, tm.tm_min, tm.tm_sec); 563 xml_node_create_text(ctx->xml, cred, NULL, "CreationDate", str); 564 } 565 566 567 static xml_node_t * build_credential_pw(struct hs20_svc *ctx, 568 const char *user, const char *realm, 569 const char *pw) 570 { 571 xml_node_t *cred; 572 573 cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); 574 if (cred == NULL) { 575 debug_print(ctx, 1, "Failed to create Credential node"); 576 return NULL; 577 } 578 add_creation_date(ctx, cred); 579 if (add_username_password(ctx, cred, user, pw) < 0) { 580 xml_node_free(ctx->xml, cred); 581 return NULL; 582 } 583 add_text_node(ctx, cred, "Realm", realm); 584 585 return cred; 586 } 587 588 589 static xml_node_t * build_credential(struct hs20_svc *ctx, 590 const char *user, const char *realm, 591 char *new_pw, size_t new_pw_len) 592 { 593 if (new_password(new_pw, new_pw_len) < 0) 594 return NULL; 595 debug_print(ctx, 1, "Update password to '%s'", new_pw); 596 return build_credential_pw(ctx, user, realm, new_pw); 597 } 598 599 600 static xml_node_t * build_credential_cert(struct hs20_svc *ctx, 601 const char *user, const char *realm, 602 const char *cert_fingerprint) 603 { 604 xml_node_t *cred, *cert; 605 606 cred = xml_node_create_root(ctx->xml, NULL, NULL, NULL, "Credential"); 607 if (cred == NULL) { 608 debug_print(ctx, 1, "Failed to create Credential node"); 609 return NULL; 610 } 611 add_creation_date(ctx, cred); 612 cert = xml_node_create(ctx->xml, cred, NULL, "DigitalCertificate"); 613 add_text_node(ctx, cert, "CertificateType", "x509v3"); 614 add_text_node(ctx, cert, "CertSHA256Fingerprint", cert_fingerprint); 615 add_text_node(ctx, cred, "Realm", realm); 616 617 return cred; 618 } 619 620 621 static xml_node_t * build_post_dev_data_response(struct hs20_svc *ctx, 622 xml_namespace_t **ret_ns, 623 const char *session_id, 624 const char *status, 625 const char *error_code) 626 { 627 xml_node_t *spp_node = NULL; 628 xml_namespace_t *ns; 629 630 spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, 631 "sppPostDevDataResponse"); 632 if (spp_node == NULL) 633 return NULL; 634 if (ret_ns) 635 *ret_ns = ns; 636 637 xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); 638 xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); 639 xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); 640 641 if (error_code) { 642 xml_node_t *node; 643 node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); 644 if (node) 645 xml_node_add_attr(ctx->xml, node, NULL, "errorCode", 646 error_code); 647 } 648 649 return spp_node; 650 } 651 652 653 static int add_update_node(struct hs20_svc *ctx, xml_node_t *spp_node, 654 xml_namespace_t *ns, const char *uri, 655 xml_node_t *upd_node) 656 { 657 xml_node_t *node, *tnds; 658 char *str; 659 660 tnds = mo_to_tnds(ctx->xml, upd_node, 0, NULL, NULL); 661 if (!tnds) 662 return -1; 663 664 str = xml_node_to_str(ctx->xml, tnds); 665 xml_node_free(ctx->xml, tnds); 666 if (str == NULL) 667 return -1; 668 node = xml_node_create_text(ctx->xml, spp_node, ns, "updateNode", str); 669 free(str); 670 671 xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", uri); 672 673 return 0; 674 } 675 676 677 static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx, 678 const char *user, const char *realm, 679 const char *session_id, 680 int machine_rem, int dmacc) 681 { 682 xml_namespace_t *ns; 683 xml_node_t *spp_node, *cred; 684 char buf[400]; 685 char new_pw[33]; 686 char *real_user = NULL; 687 char *status; 688 char *cert; 689 690 if (dmacc) { 691 real_user = db_get_val(ctx, user, realm, "identity", dmacc); 692 if (real_user == NULL) { 693 debug_print(ctx, 1, "Could not find user identity for " 694 "dmacc user '%s'", user); 695 return NULL; 696 } 697 } 698 699 cert = db_get_val(ctx, user, realm, "cert", dmacc); 700 if (cert && cert[0] == '\0') 701 cert = NULL; 702 if (cert) { 703 cred = build_credential_cert(ctx, real_user ? real_user : user, 704 realm, cert); 705 } else { 706 cred = build_credential(ctx, real_user ? real_user : user, 707 realm, new_pw, sizeof(new_pw)); 708 } 709 free(real_user); 710 if (!cred) { 711 debug_print(ctx, 1, "Could not build credential"); 712 return NULL; 713 } 714 715 status = "Remediation complete, request sppUpdateResponse"; 716 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 717 NULL); 718 if (spp_node == NULL) { 719 debug_print(ctx, 1, "Could not build sppPostDevDataResponse"); 720 return NULL; 721 } 722 723 snprintf(buf, sizeof(buf), 724 "./Wi-Fi/%s/PerProviderSubscription/Credential1/Credential", 725 realm); 726 727 if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { 728 debug_print(ctx, 1, "Could not add update node"); 729 xml_node_free(ctx->xml, spp_node); 730 return NULL; 731 } 732 733 hs20_eventlog_node(ctx, user, realm, session_id, 734 machine_rem ? "machine remediation" : 735 "user remediation", cred); 736 xml_node_free(ctx->xml, cred); 737 738 if (cert) { 739 debug_print(ctx, 1, "Certificate credential - no need for DB " 740 "password update on success notification"); 741 } else { 742 debug_print(ctx, 1, "Request DB password update on success " 743 "notification"); 744 db_add_session(ctx, user, realm, session_id, new_pw, NULL, 745 UPDATE_PASSWORD); 746 } 747 748 return spp_node; 749 } 750 751 752 static xml_node_t * machine_remediation(struct hs20_svc *ctx, 753 const char *user, 754 const char *realm, 755 const char *session_id, int dmacc) 756 { 757 return build_sub_rem_resp(ctx, user, realm, session_id, 1, dmacc); 758 } 759 760 761 static xml_node_t * policy_remediation(struct hs20_svc *ctx, 762 const char *user, const char *realm, 763 const char *session_id, int dmacc) 764 { 765 xml_namespace_t *ns; 766 xml_node_t *spp_node, *policy; 767 char buf[400]; 768 const char *status; 769 770 hs20_eventlog(ctx, user, realm, session_id, 771 "requires policy remediation", NULL); 772 773 db_add_session(ctx, user, realm, session_id, NULL, NULL, 774 POLICY_REMEDIATION); 775 776 policy = build_policy(ctx, user, realm, dmacc); 777 if (!policy) { 778 return build_post_dev_data_response( 779 ctx, NULL, session_id, 780 "No update available at this time", NULL); 781 } 782 783 status = "Remediation complete, request sppUpdateResponse"; 784 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 785 NULL); 786 if (spp_node == NULL) 787 return NULL; 788 789 snprintf(buf, sizeof(buf), 790 "./Wi-Fi/%s/PerProviderSubscription/Credential1/Policy", 791 realm); 792 793 if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { 794 xml_node_free(ctx->xml, spp_node); 795 xml_node_free(ctx->xml, policy); 796 return NULL; 797 } 798 799 hs20_eventlog_node(ctx, user, realm, session_id, 800 "policy update (sub rem)", policy); 801 xml_node_free(ctx->xml, policy); 802 803 return spp_node; 804 } 805 806 807 static xml_node_t * browser_remediation(struct hs20_svc *ctx, 808 const char *session_id, 809 const char *redirect_uri, 810 const char *uri) 811 { 812 xml_namespace_t *ns; 813 xml_node_t *spp_node, *exec_node; 814 815 if (redirect_uri == NULL) { 816 debug_print(ctx, 1, "Missing redirectURI attribute for user " 817 "remediation"); 818 return NULL; 819 } 820 debug_print(ctx, 1, "redirectURI %s", redirect_uri); 821 822 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 823 NULL); 824 if (spp_node == NULL) 825 return NULL; 826 827 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 828 xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", 829 uri); 830 return spp_node; 831 } 832 833 834 static xml_node_t * user_remediation(struct hs20_svc *ctx, const char *user, 835 const char *realm, const char *session_id, 836 const char *redirect_uri) 837 { 838 char uri[300], *val; 839 840 hs20_eventlog(ctx, user, realm, session_id, 841 "requires user remediation", NULL); 842 val = db_get_osu_config_val(ctx, realm, "remediation_url"); 843 if (val == NULL) 844 return NULL; 845 846 db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, 847 USER_REMEDIATION); 848 849 snprintf(uri, sizeof(uri), "%s%s", val, session_id); 850 os_free(val); 851 return browser_remediation(ctx, session_id, redirect_uri, uri); 852 } 853 854 855 static xml_node_t * free_remediation(struct hs20_svc *ctx, 856 const char *user, const char *realm, 857 const char *session_id, 858 const char *redirect_uri) 859 { 860 char uri[300], *val; 861 862 hs20_eventlog(ctx, user, realm, session_id, 863 "requires free/public account remediation", NULL); 864 val = db_get_osu_config_val(ctx, realm, "free_remediation_url"); 865 if (val == NULL) 866 return NULL; 867 868 db_add_session(ctx, user, realm, session_id, NULL, redirect_uri, 869 FREE_REMEDIATION); 870 871 snprintf(uri, sizeof(uri), "%s%s", val, session_id); 872 os_free(val); 873 return browser_remediation(ctx, session_id, redirect_uri, uri); 874 } 875 876 877 static xml_node_t * no_sub_rem(struct hs20_svc *ctx, 878 const char *user, const char *realm, 879 const char *session_id) 880 { 881 const char *status; 882 883 hs20_eventlog(ctx, user, realm, session_id, 884 "no subscription mediation available", NULL); 885 886 status = "No update available at this time"; 887 return build_post_dev_data_response(ctx, NULL, session_id, status, 888 NULL); 889 } 890 891 892 static xml_node_t * hs20_subscription_remediation(struct hs20_svc *ctx, 893 const char *user, 894 const char *realm, 895 const char *session_id, 896 int dmacc, 897 const char *redirect_uri) 898 { 899 char *type, *identity; 900 xml_node_t *ret; 901 char *free_account; 902 903 identity = db_get_val(ctx, user, realm, "identity", dmacc); 904 if (identity == NULL || strlen(identity) == 0) { 905 hs20_eventlog(ctx, user, realm, session_id, 906 "user not found in database for remediation", 907 NULL); 908 os_free(identity); 909 return build_post_dev_data_response(ctx, NULL, session_id, 910 "Error occurred", 911 "Not found"); 912 } 913 os_free(identity); 914 915 free_account = db_get_osu_config_val(ctx, realm, "free_account"); 916 if (free_account && strcmp(free_account, user) == 0) { 917 free(free_account); 918 return no_sub_rem(ctx, user, realm, session_id); 919 } 920 free(free_account); 921 922 type = db_get_val(ctx, user, realm, "remediation", dmacc); 923 if (type && strcmp(type, "free") != 0) { 924 char *val; 925 int shared = 0; 926 val = db_get_val(ctx, user, realm, "shared", dmacc); 927 if (val) 928 shared = atoi(val); 929 free(val); 930 if (shared) { 931 free(type); 932 return no_sub_rem(ctx, user, realm, session_id); 933 } 934 } 935 if (type && strcmp(type, "user") == 0) 936 ret = user_remediation(ctx, user, realm, session_id, 937 redirect_uri); 938 else if (type && strcmp(type, "free") == 0) 939 ret = free_remediation(ctx, user, realm, session_id, 940 redirect_uri); 941 else if (type && strcmp(type, "policy") == 0) 942 ret = policy_remediation(ctx, user, realm, session_id, dmacc); 943 else 944 ret = machine_remediation(ctx, user, realm, session_id, dmacc); 945 free(type); 946 947 return ret; 948 } 949 950 951 static xml_node_t * build_policy(struct hs20_svc *ctx, const char *user, 952 const char *realm, int use_dmacc) 953 { 954 char *policy_id; 955 char fname[200]; 956 xml_node_t *policy, *node; 957 958 policy_id = db_get_val(ctx, user, realm, "policy", use_dmacc); 959 if (policy_id == NULL || strlen(policy_id) == 0) { 960 free(policy_id); 961 policy_id = strdup("default"); 962 if (policy_id == NULL) 963 return NULL; 964 } 965 966 snprintf(fname, sizeof(fname), "%s/spp/policy/%s.xml", 967 ctx->root_dir, policy_id); 968 free(policy_id); 969 debug_print(ctx, 1, "Use policy file %s", fname); 970 971 policy = node_from_file(ctx->xml, fname); 972 if (policy == NULL) 973 return NULL; 974 975 node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate/URI"); 976 if (node) { 977 char *url; 978 url = db_get_osu_config_val(ctx, realm, "policy_url"); 979 if (url == NULL) { 980 xml_node_free(ctx->xml, policy); 981 return NULL; 982 } 983 xml_node_set_text(ctx->xml, node, url); 984 free(url); 985 } 986 987 node = get_node_uri(ctx->xml, policy, "Policy/PolicyUpdate"); 988 if (node && use_dmacc) { 989 char *pw; 990 pw = db_get_val(ctx, user, realm, "osu_password", use_dmacc); 991 if (pw == NULL || 992 build_username_password(ctx, node, user, pw) == NULL) { 993 debug_print(ctx, 1, "Failed to add Policy/PolicyUpdate/" 994 "UsernamePassword"); 995 free(pw); 996 xml_node_free(ctx->xml, policy); 997 return NULL; 998 } 999 free(pw); 1000 } 1001 1002 return policy; 1003 } 1004 1005 1006 static xml_node_t * hs20_policy_update(struct hs20_svc *ctx, 1007 const char *user, const char *realm, 1008 const char *session_id, int dmacc) 1009 { 1010 xml_namespace_t *ns; 1011 xml_node_t *spp_node; 1012 xml_node_t *policy; 1013 char buf[400]; 1014 const char *status; 1015 char *identity; 1016 1017 identity = db_get_val(ctx, user, realm, "identity", dmacc); 1018 if (identity == NULL || strlen(identity) == 0) { 1019 hs20_eventlog(ctx, user, realm, session_id, 1020 "user not found in database for policy update", 1021 NULL); 1022 os_free(identity); 1023 return build_post_dev_data_response(ctx, NULL, session_id, 1024 "Error occurred", 1025 "Not found"); 1026 } 1027 os_free(identity); 1028 1029 policy = build_policy(ctx, user, realm, dmacc); 1030 if (!policy) { 1031 return build_post_dev_data_response( 1032 ctx, NULL, session_id, 1033 "No update available at this time", NULL); 1034 } 1035 1036 db_add_session(ctx, user, realm, session_id, NULL, NULL, POLICY_UPDATE); 1037 1038 status = "Update complete, request sppUpdateResponse"; 1039 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1040 NULL); 1041 if (spp_node == NULL) 1042 return NULL; 1043 1044 snprintf(buf, sizeof(buf), 1045 "./Wi-Fi/%s/PerProviderSubscription/Credential1/Policy", 1046 realm); 1047 1048 if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) { 1049 xml_node_free(ctx->xml, spp_node); 1050 xml_node_free(ctx->xml, policy); 1051 return NULL; 1052 } 1053 1054 hs20_eventlog_node(ctx, user, realm, session_id, "policy update", 1055 policy); 1056 xml_node_free(ctx->xml, policy); 1057 1058 return spp_node; 1059 } 1060 1061 1062 static xml_node_t * spp_get_mo(struct hs20_svc *ctx, xml_node_t *node, 1063 const char *urn, int *valid, char **ret_err) 1064 { 1065 xml_node_t *child, *tnds, *mo; 1066 const char *name; 1067 char *mo_urn; 1068 char *str; 1069 char fname[200]; 1070 1071 *valid = -1; 1072 if (ret_err) 1073 *ret_err = NULL; 1074 1075 xml_node_for_each_child(ctx->xml, child, node) { 1076 xml_node_for_each_check(ctx->xml, child); 1077 name = xml_node_get_localname(ctx->xml, child); 1078 if (strcmp(name, "moContainer") != 0) 1079 continue; 1080 mo_urn = xml_node_get_attr_value_ns(ctx->xml, child, SPP_NS_URI, 1081 "moURN"); 1082 if (strcasecmp(urn, mo_urn) == 0) { 1083 xml_node_get_attr_value_free(ctx->xml, mo_urn); 1084 break; 1085 } 1086 xml_node_get_attr_value_free(ctx->xml, mo_urn); 1087 } 1088 1089 if (child == NULL) 1090 return NULL; 1091 1092 debug_print(ctx, 1, "moContainer text for %s", urn); 1093 debug_dump_node(ctx, "moContainer", child); 1094 1095 str = xml_node_get_text(ctx->xml, child); 1096 debug_print(ctx, 1, "moContainer payload: '%s'", str); 1097 tnds = xml_node_from_buf(ctx->xml, str); 1098 xml_node_get_text_free(ctx->xml, str); 1099 if (tnds == NULL) { 1100 debug_print(ctx, 1, "could not parse moContainer text"); 1101 return NULL; 1102 } 1103 1104 snprintf(fname, sizeof(fname), "%s/spp/dm_ddf-v1_2.dtd", ctx->root_dir); 1105 if (xml_validate_dtd(ctx->xml, tnds, fname, ret_err) == 0) 1106 *valid = 1; 1107 else if (ret_err && *ret_err && 1108 os_strcmp(*ret_err, "No declaration for attribute xmlns of element MgmtTree\n") == 0) { 1109 free(*ret_err); 1110 debug_print(ctx, 1, "Ignore OMA-DM DDF DTD validation error for MgmtTree namespace declaration with xmlns attribute"); 1111 *ret_err = NULL; 1112 *valid = 1; 1113 } else 1114 *valid = 0; 1115 1116 mo = tnds_to_mo(ctx->xml, tnds); 1117 xml_node_free(ctx->xml, tnds); 1118 if (mo == NULL) { 1119 debug_print(ctx, 1, "invalid moContainer for %s", urn); 1120 } 1121 1122 return mo; 1123 } 1124 1125 1126 static xml_node_t * spp_exec_upload_mo(struct hs20_svc *ctx, 1127 const char *session_id, const char *urn) 1128 { 1129 xml_namespace_t *ns; 1130 xml_node_t *spp_node, *node, *exec_node; 1131 1132 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1133 NULL); 1134 if (spp_node == NULL) 1135 return NULL; 1136 1137 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1138 1139 node = xml_node_create(ctx->xml, exec_node, ns, "uploadMO"); 1140 xml_node_add_attr(ctx->xml, node, ns, "moURN", urn); 1141 1142 return spp_node; 1143 } 1144 1145 1146 static xml_node_t * hs20_subscription_registration(struct hs20_svc *ctx, 1147 const char *realm, 1148 const char *session_id, 1149 const char *redirect_uri) 1150 { 1151 xml_namespace_t *ns; 1152 xml_node_t *spp_node, *exec_node; 1153 char uri[300], *val; 1154 1155 if (db_add_session(ctx, NULL, realm, session_id, NULL, redirect_uri, 1156 SUBSCRIPTION_REGISTRATION) < 0) 1157 return NULL; 1158 val = db_get_osu_config_val(ctx, realm, "signup_url"); 1159 if (val == NULL) 1160 return NULL; 1161 1162 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1163 NULL); 1164 if (spp_node == NULL) 1165 return NULL; 1166 1167 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1168 1169 snprintf(uri, sizeof(uri), "%s%s", val, session_id); 1170 os_free(val); 1171 xml_node_create_text(ctx->xml, exec_node, ns, "launchBrowserToURI", 1172 uri); 1173 return spp_node; 1174 } 1175 1176 1177 static xml_node_t * hs20_user_input_remediation(struct hs20_svc *ctx, 1178 const char *user, 1179 const char *realm, int dmacc, 1180 const char *session_id) 1181 { 1182 return build_sub_rem_resp(ctx, user, realm, session_id, 0, dmacc); 1183 } 1184 1185 1186 static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm, 1187 const char *field) 1188 { 1189 char *cmd; 1190 struct get_db_field_data data; 1191 1192 cmd = sqlite3_mprintf("SELECT value FROM osu_config WHERE realm=%Q AND " 1193 "field=%Q", realm, field); 1194 if (cmd == NULL) 1195 return NULL; 1196 debug_print(ctx, 1, "DB: %s", cmd); 1197 memset(&data, 0, sizeof(data)); 1198 data.field = "value"; 1199 if (sqlite3_exec(ctx->db, cmd, get_db_field, &data, NULL) != SQLITE_OK) 1200 { 1201 debug_print(ctx, 1, "DB: Could not find osu_config %s: %s", 1202 realm, sqlite3_errmsg(ctx->db)); 1203 sqlite3_free(cmd); 1204 return NULL; 1205 } 1206 sqlite3_free(cmd); 1207 1208 debug_print(ctx, 1, "DB: return '%s'", data.value); 1209 return data.value; 1210 } 1211 1212 1213 static xml_node_t * build_pps(struct hs20_svc *ctx, 1214 const char *user, const char *realm, 1215 const char *pw, const char *cert, 1216 int machine_managed) 1217 { 1218 xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp; 1219 xml_node_t *cred, *eap, *userpw; 1220 1221 pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 1222 "PerProviderSubscription"); 1223 if (pps == NULL) 1224 return NULL; 1225 1226 add_text_node(ctx, pps, "UpdateIdentifier", "1"); 1227 1228 c = xml_node_create(ctx->xml, pps, NULL, "Credential1"); 1229 1230 add_text_node(ctx, c, "CredentialPriority", "1"); 1231 1232 aaa = xml_node_create(ctx->xml, c, NULL, "AAAServerTrustRoot"); 1233 aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1"); 1234 add_text_node_conf(ctx, realm, aaa1, "CertURL", 1235 "aaa_trust_root_cert_url"); 1236 add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint", 1237 "aaa_trust_root_cert_fingerprint"); 1238 1239 upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate"); 1240 add_text_node(ctx, upd, "UpdateInterval", "4294967295"); 1241 add_text_node(ctx, upd, "UpdateMethod", "ClientInitiated"); 1242 add_text_node(ctx, upd, "Restriction", "HomeSP"); 1243 add_text_node_conf(ctx, realm, upd, "URI", "spp_http_auth_url"); 1244 trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot"); 1245 add_text_node_conf(ctx, realm, trust, "CertURL", "trust_root_cert_url"); 1246 add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint", 1247 "trust_root_cert_fingerprint"); 1248 1249 homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP"); 1250 add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name"); 1251 add_text_node_conf(ctx, realm, homesp, "FQDN", "fqdn"); 1252 1253 xml_node_create(ctx->xml, c, NULL, "SubscriptionParameters"); 1254 1255 cred = xml_node_create(ctx->xml, c, NULL, "Credential"); 1256 add_creation_date(ctx, cred); 1257 if (cert) { 1258 xml_node_t *dc; 1259 dc = xml_node_create(ctx->xml, cred, NULL, 1260 "DigitalCertificate"); 1261 add_text_node(ctx, dc, "CertificateType", "x509v3"); 1262 add_text_node(ctx, dc, "CertSHA256Fingerprint", cert); 1263 } else { 1264 userpw = build_username_password(ctx, cred, user, pw); 1265 add_text_node(ctx, userpw, "MachineManaged", 1266 machine_managed ? "TRUE" : "FALSE"); 1267 eap = xml_node_create(ctx->xml, userpw, NULL, "EAPMethod"); 1268 add_text_node(ctx, eap, "EAPType", "21"); 1269 add_text_node(ctx, eap, "InnerMethod", "MS-CHAP-V2"); 1270 } 1271 add_text_node(ctx, cred, "Realm", realm); 1272 1273 return pps; 1274 } 1275 1276 1277 static xml_node_t * spp_exec_get_certificate(struct hs20_svc *ctx, 1278 const char *session_id, 1279 const char *user, 1280 const char *realm) 1281 { 1282 xml_namespace_t *ns; 1283 xml_node_t *spp_node, *enroll, *exec_node; 1284 char *val; 1285 char password[11]; 1286 char *b64; 1287 1288 if (new_password(password, sizeof(password)) < 0) 1289 return NULL; 1290 1291 spp_node = build_post_dev_data_response(ctx, &ns, session_id, "OK", 1292 NULL); 1293 if (spp_node == NULL) 1294 return NULL; 1295 1296 exec_node = xml_node_create(ctx->xml, spp_node, ns, "exec"); 1297 1298 enroll = xml_node_create(ctx->xml, exec_node, ns, "getCertificate"); 1299 xml_node_add_attr(ctx->xml, enroll, NULL, "enrollmentProtocol", "EST"); 1300 1301 val = db_get_osu_config_val(ctx, realm, "est_url"); 1302 xml_node_create_text(ctx->xml, enroll, ns, "enrollmentServerURI", 1303 val ? val : ""); 1304 os_free(val); 1305 xml_node_create_text(ctx->xml, enroll, ns, "estUserID", user); 1306 1307 b64 = (char *) base64_encode((unsigned char *) password, 1308 strlen(password), NULL); 1309 if (b64 == NULL) { 1310 xml_node_free(ctx->xml, spp_node); 1311 return NULL; 1312 } 1313 xml_node_create_text(ctx->xml, enroll, ns, "estPassword", b64); 1314 free(b64); 1315 1316 db_update_session_password(ctx, user, realm, session_id, password); 1317 1318 return spp_node; 1319 } 1320 1321 1322 static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx, 1323 const char *session_id, 1324 int enrollment_done) 1325 { 1326 xml_namespace_t *ns; 1327 xml_node_t *spp_node, *node = NULL; 1328 xml_node_t *pps, *tnds; 1329 char buf[400]; 1330 char *str; 1331 char *user, *realm, *pw, *type, *mm; 1332 const char *status; 1333 int cert = 0; 1334 int machine_managed = 0; 1335 char *fingerprint; 1336 1337 user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); 1338 realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); 1339 pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); 1340 1341 if (!user || !realm || !pw) { 1342 debug_print(ctx, 1, "Could not find session info from DB for " 1343 "the new subscription"); 1344 free(user); 1345 free(realm); 1346 free(pw); 1347 return NULL; 1348 } 1349 1350 mm = db_get_session_val(ctx, NULL, NULL, session_id, "machine_managed"); 1351 if (mm && atoi(mm)) 1352 machine_managed = 1; 1353 free(mm); 1354 1355 type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); 1356 if (type && strcmp(type, "cert") == 0) 1357 cert = 1; 1358 free(type); 1359 1360 if (cert && !enrollment_done) { 1361 xml_node_t *ret; 1362 hs20_eventlog(ctx, user, realm, session_id, 1363 "request client certificate enrollment", NULL); 1364 ret = spp_exec_get_certificate(ctx, session_id, user, realm); 1365 free(user); 1366 free(realm); 1367 free(pw); 1368 return ret; 1369 } 1370 1371 if (!cert && strlen(pw) == 0) { 1372 machine_managed = 1; 1373 free(pw); 1374 pw = malloc(11); 1375 if (pw == NULL || new_password(pw, 11) < 0) { 1376 free(user); 1377 free(realm); 1378 free(pw); 1379 return NULL; 1380 } 1381 } 1382 1383 status = "Provisioning complete, request sppUpdateResponse"; 1384 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1385 NULL); 1386 if (spp_node == NULL) 1387 return NULL; 1388 1389 fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); 1390 pps = build_pps(ctx, user, realm, pw, 1391 fingerprint ? fingerprint : NULL, machine_managed); 1392 free(fingerprint); 1393 if (!pps) { 1394 xml_node_free(ctx->xml, spp_node); 1395 free(user); 1396 free(realm); 1397 free(pw); 1398 return NULL; 1399 } 1400 1401 debug_print(ctx, 1, "Request DB subscription registration on success " 1402 "notification"); 1403 if (machine_managed) { 1404 db_update_session_password(ctx, user, realm, session_id, pw); 1405 db_update_session_machine_managed(ctx, user, realm, session_id, 1406 machine_managed); 1407 } 1408 db_add_session_pps(ctx, user, realm, session_id, pps); 1409 1410 hs20_eventlog_node(ctx, user, realm, session_id, 1411 "new subscription", pps); 1412 free(user); 1413 free(pw); 1414 1415 tnds = mo_to_tnds(ctx->xml, pps, 0, URN_HS20_PPS, NULL); 1416 xml_node_free(ctx->xml, pps); 1417 if (!tnds) { 1418 xml_node_free(ctx->xml, spp_node); 1419 free(realm); 1420 return NULL; 1421 } 1422 1423 str = xml_node_to_str(ctx->xml, tnds); 1424 xml_node_free(ctx->xml, tnds); 1425 if (str == NULL) { 1426 xml_node_free(ctx->xml, spp_node); 1427 free(realm); 1428 return NULL; 1429 } 1430 1431 node = xml_node_create_text(ctx->xml, spp_node, ns, "addMO", str); 1432 free(str); 1433 snprintf(buf, sizeof(buf), "./Wi-Fi/%s/PerProviderSubscription", realm); 1434 free(realm); 1435 xml_node_add_attr(ctx->xml, node, ns, "managementTreeURI", buf); 1436 xml_node_add_attr(ctx->xml, node, ns, "moURN", URN_HS20_PPS); 1437 1438 return spp_node; 1439 } 1440 1441 1442 static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx, 1443 const char *user, 1444 const char *realm, 1445 const char *session_id) 1446 { 1447 xml_namespace_t *ns; 1448 xml_node_t *spp_node; 1449 xml_node_t *cred; 1450 char buf[400]; 1451 char *status; 1452 char *free_account, *pw; 1453 1454 free_account = db_get_osu_config_val(ctx, realm, "free_account"); 1455 if (free_account == NULL) 1456 return NULL; 1457 pw = db_get_val(ctx, free_account, realm, "password", 0); 1458 if (pw == NULL) { 1459 free(free_account); 1460 return NULL; 1461 } 1462 1463 cred = build_credential_pw(ctx, free_account, realm, pw); 1464 free(free_account); 1465 free(pw); 1466 if (!cred) { 1467 xml_node_free(ctx->xml, cred); 1468 return NULL; 1469 } 1470 1471 status = "Remediation complete, request sppUpdateResponse"; 1472 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1473 NULL); 1474 if (spp_node == NULL) 1475 return NULL; 1476 1477 snprintf(buf, sizeof(buf), 1478 "./Wi-Fi/%s/PerProviderSubscription/Credential1/Credential", 1479 realm); 1480 1481 if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) { 1482 xml_node_free(ctx->xml, spp_node); 1483 return NULL; 1484 } 1485 1486 hs20_eventlog_node(ctx, user, realm, session_id, 1487 "free/public remediation", cred); 1488 xml_node_free(ctx->xml, cred); 1489 1490 return spp_node; 1491 } 1492 1493 1494 static xml_node_t * hs20_user_input_complete(struct hs20_svc *ctx, 1495 const char *user, 1496 const char *realm, int dmacc, 1497 const char *session_id) 1498 { 1499 char *val; 1500 enum hs20_session_operation oper; 1501 1502 val = db_get_session_val(ctx, user, realm, session_id, "operation"); 1503 if (val == NULL) { 1504 debug_print(ctx, 1, "No session %s found to continue", 1505 session_id); 1506 return NULL; 1507 } 1508 oper = atoi(val); 1509 free(val); 1510 1511 if (oper == USER_REMEDIATION) { 1512 return hs20_user_input_remediation(ctx, user, realm, dmacc, 1513 session_id); 1514 } 1515 1516 if (oper == FREE_REMEDIATION) { 1517 return hs20_user_input_free_remediation(ctx, user, realm, 1518 session_id); 1519 } 1520 1521 if (oper == SUBSCRIPTION_REGISTRATION) { 1522 return hs20_user_input_registration(ctx, session_id, 0); 1523 } 1524 1525 debug_print(ctx, 1, "User session %s not in state for user input " 1526 "completion", session_id); 1527 return NULL; 1528 } 1529 1530 1531 static xml_node_t * hs20_cert_enroll_completed(struct hs20_svc *ctx, 1532 const char *user, 1533 const char *realm, int dmacc, 1534 const char *session_id) 1535 { 1536 char *val; 1537 enum hs20_session_operation oper; 1538 1539 val = db_get_session_val(ctx, user, realm, session_id, "operation"); 1540 if (val == NULL) { 1541 debug_print(ctx, 1, "No session %s found to continue", 1542 session_id); 1543 return NULL; 1544 } 1545 oper = atoi(val); 1546 free(val); 1547 1548 if (oper == SUBSCRIPTION_REGISTRATION) 1549 return hs20_user_input_registration(ctx, session_id, 1); 1550 1551 debug_print(ctx, 1, "User session %s not in state for certificate " 1552 "enrollment completion", session_id); 1553 return NULL; 1554 } 1555 1556 1557 static xml_node_t * hs20_cert_enroll_failed(struct hs20_svc *ctx, 1558 const char *user, 1559 const char *realm, int dmacc, 1560 const char *session_id) 1561 { 1562 char *val; 1563 enum hs20_session_operation oper; 1564 xml_node_t *spp_node, *node; 1565 char *status; 1566 xml_namespace_t *ns; 1567 1568 val = db_get_session_val(ctx, user, realm, session_id, "operation"); 1569 if (val == NULL) { 1570 debug_print(ctx, 1, "No session %s found to continue", 1571 session_id); 1572 return NULL; 1573 } 1574 oper = atoi(val); 1575 free(val); 1576 1577 if (oper != SUBSCRIPTION_REGISTRATION) { 1578 debug_print(ctx, 1, "User session %s not in state for " 1579 "enrollment failure", session_id); 1580 return NULL; 1581 } 1582 1583 status = "Error occurred"; 1584 spp_node = build_post_dev_data_response(ctx, &ns, session_id, status, 1585 NULL); 1586 if (spp_node == NULL) 1587 return NULL; 1588 node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); 1589 xml_node_add_attr(ctx->xml, node, NULL, "errorCode", 1590 "Credentials cannot be provisioned at this time"); 1591 db_remove_session(ctx, user, realm, session_id); 1592 1593 return spp_node; 1594 } 1595 1596 1597 static xml_node_t * hs20_spp_post_dev_data(struct hs20_svc *ctx, 1598 xml_node_t *node, 1599 const char *user, 1600 const char *realm, 1601 const char *session_id, 1602 int dmacc) 1603 { 1604 const char *req_reason; 1605 char *redirect_uri = NULL; 1606 char *req_reason_buf = NULL; 1607 char str[200]; 1608 xml_node_t *ret = NULL, *devinfo = NULL, *devdetail = NULL; 1609 xml_node_t *mo; 1610 char *version; 1611 int valid; 1612 char *supp, *pos; 1613 char *err; 1614 1615 version = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, 1616 "sppVersion"); 1617 if (version == NULL || strstr(version, "1.0") == NULL) { 1618 ret = build_post_dev_data_response( 1619 ctx, NULL, session_id, "Error occurred", 1620 "SPP version not supported"); 1621 hs20_eventlog_node(ctx, user, realm, session_id, 1622 "Unsupported sppVersion", ret); 1623 xml_node_get_attr_value_free(ctx->xml, version); 1624 return ret; 1625 } 1626 xml_node_get_attr_value_free(ctx->xml, version); 1627 1628 mo = get_node(ctx->xml, node, "supportedMOList"); 1629 if (mo == NULL) { 1630 ret = build_post_dev_data_response( 1631 ctx, NULL, session_id, "Error occurred", 1632 "Other"); 1633 hs20_eventlog_node(ctx, user, realm, session_id, 1634 "No supportedMOList element", ret); 1635 return ret; 1636 } 1637 supp = xml_node_get_text(ctx->xml, mo); 1638 for (pos = supp; pos && *pos; pos++) 1639 *pos = tolower(*pos); 1640 if (supp == NULL || 1641 strstr(supp, URN_OMA_DM_DEVINFO) == NULL || 1642 strstr(supp, URN_OMA_DM_DEVDETAIL) == NULL || 1643 strstr(supp, URN_HS20_PPS) == NULL) { 1644 xml_node_get_text_free(ctx->xml, supp); 1645 ret = build_post_dev_data_response( 1646 ctx, NULL, session_id, "Error occurred", 1647 "One or more mandatory MOs not supported"); 1648 hs20_eventlog_node(ctx, user, realm, session_id, 1649 "Unsupported MOs", ret); 1650 return ret; 1651 } 1652 xml_node_get_text_free(ctx->xml, supp); 1653 1654 req_reason_buf = xml_node_get_attr_value(ctx->xml, node, 1655 "requestReason"); 1656 if (req_reason_buf == NULL) { 1657 debug_print(ctx, 1, "No requestReason attribute"); 1658 return NULL; 1659 } 1660 req_reason = req_reason_buf; 1661 1662 redirect_uri = xml_node_get_attr_value(ctx->xml, node, "redirectURI"); 1663 1664 debug_print(ctx, 1, "requestReason: %s sessionID: %s redirectURI: %s", 1665 req_reason, session_id, redirect_uri); 1666 snprintf(str, sizeof(str), "sppPostDevData: requestReason=%s", 1667 req_reason); 1668 hs20_eventlog(ctx, user, realm, session_id, str, NULL); 1669 1670 devinfo = spp_get_mo(ctx, node, URN_OMA_DM_DEVINFO, &valid, &err); 1671 if (devinfo == NULL) { 1672 ret = build_post_dev_data_response(ctx, NULL, session_id, 1673 "Error occurred", "Other"); 1674 hs20_eventlog_node(ctx, user, realm, session_id, 1675 "No DevInfo moContainer in sppPostDevData", 1676 ret); 1677 os_free(err); 1678 goto out; 1679 } 1680 1681 hs20_eventlog_node(ctx, user, realm, session_id, 1682 "Received DevInfo MO", devinfo); 1683 if (valid == 0) { 1684 hs20_eventlog(ctx, user, realm, session_id, 1685 "OMA-DM DDF DTD validation errors in DevInfo MO", 1686 err); 1687 ret = build_post_dev_data_response(ctx, NULL, session_id, 1688 "Error occurred", "Other"); 1689 os_free(err); 1690 goto out; 1691 } 1692 os_free(err); 1693 if (user) 1694 db_update_mo(ctx, user, realm, "devinfo", devinfo); 1695 1696 devdetail = spp_get_mo(ctx, node, URN_OMA_DM_DEVDETAIL, &valid, &err); 1697 if (devdetail == NULL) { 1698 ret = build_post_dev_data_response(ctx, NULL, session_id, 1699 "Error occurred", "Other"); 1700 hs20_eventlog_node(ctx, user, realm, session_id, 1701 "No DevDetail moContainer in sppPostDevData", 1702 ret); 1703 os_free(err); 1704 goto out; 1705 } 1706 1707 hs20_eventlog_node(ctx, user, realm, session_id, 1708 "Received DevDetail MO", devdetail); 1709 if (valid == 0) { 1710 hs20_eventlog(ctx, user, realm, session_id, 1711 "OMA-DM DDF DTD validation errors " 1712 "in DevDetail MO", err); 1713 ret = build_post_dev_data_response(ctx, NULL, session_id, 1714 "Error occurred", "Other"); 1715 os_free(err); 1716 goto out; 1717 } 1718 os_free(err); 1719 if (user) 1720 db_update_mo(ctx, user, realm, "devdetail", devdetail); 1721 1722 if (user) 1723 mo = spp_get_mo(ctx, node, URN_HS20_PPS, &valid, &err); 1724 else { 1725 mo = NULL; 1726 err = NULL; 1727 } 1728 if (user && mo) { 1729 hs20_eventlog_node(ctx, user, realm, session_id, 1730 "Received PPS MO", mo); 1731 if (valid == 0) { 1732 hs20_eventlog(ctx, user, realm, session_id, 1733 "OMA-DM DDF DTD validation errors " 1734 "in PPS MO", err); 1735 xml_node_get_attr_value_free(ctx->xml, redirect_uri); 1736 os_free(err); 1737 return build_post_dev_data_response( 1738 ctx, NULL, session_id, 1739 "Error occurred", "Other"); 1740 } 1741 db_update_mo(ctx, user, realm, "pps", mo); 1742 db_update_val(ctx, user, realm, "fetch_pps", "0", dmacc); 1743 xml_node_free(ctx->xml, mo); 1744 } 1745 os_free(err); 1746 1747 if (user && !mo) { 1748 char *fetch; 1749 int fetch_pps; 1750 1751 fetch = db_get_val(ctx, user, realm, "fetch_pps", dmacc); 1752 fetch_pps = fetch ? atoi(fetch) : 0; 1753 free(fetch); 1754 1755 if (fetch_pps) { 1756 enum hs20_session_operation oper; 1757 if (strcasecmp(req_reason, "Subscription remediation") 1758 == 0) 1759 oper = CONTINUE_SUBSCRIPTION_REMEDIATION; 1760 else if (strcasecmp(req_reason, "Policy update") == 0) 1761 oper = CONTINUE_POLICY_UPDATE; 1762 else 1763 oper = NO_OPERATION; 1764 if (db_add_session(ctx, user, realm, session_id, NULL, 1765 NULL, oper) < 0) 1766 goto out; 1767 1768 ret = spp_exec_upload_mo(ctx, session_id, 1769 URN_HS20_PPS); 1770 hs20_eventlog_node(ctx, user, realm, session_id, 1771 "request PPS MO upload", 1772 ret); 1773 goto out; 1774 } 1775 } 1776 1777 if (user && strcasecmp(req_reason, "MO upload") == 0) { 1778 char *val = db_get_session_val(ctx, user, realm, session_id, 1779 "operation"); 1780 enum hs20_session_operation oper; 1781 if (!val) { 1782 debug_print(ctx, 1, "No session %s found to continue", 1783 session_id); 1784 goto out; 1785 } 1786 oper = atoi(val); 1787 free(val); 1788 if (oper == CONTINUE_SUBSCRIPTION_REMEDIATION) 1789 req_reason = "Subscription remediation"; 1790 else if (oper == CONTINUE_POLICY_UPDATE) 1791 req_reason = "Policy update"; 1792 else { 1793 debug_print(ctx, 1, 1794 "No pending operation in session %s", 1795 session_id); 1796 goto out; 1797 } 1798 } 1799 1800 if (strcasecmp(req_reason, "Subscription registration") == 0) { 1801 ret = hs20_subscription_registration(ctx, realm, session_id, 1802 redirect_uri); 1803 hs20_eventlog_node(ctx, user, realm, session_id, 1804 "subscription registration response", 1805 ret); 1806 goto out; 1807 } 1808 if (user && strcasecmp(req_reason, "Subscription remediation") == 0) { 1809 ret = hs20_subscription_remediation(ctx, user, realm, 1810 session_id, dmacc, 1811 redirect_uri); 1812 hs20_eventlog_node(ctx, user, realm, session_id, 1813 "subscription remediation response", 1814 ret); 1815 goto out; 1816 } 1817 if (user && strcasecmp(req_reason, "Policy update") == 0) { 1818 ret = hs20_policy_update(ctx, user, realm, session_id, dmacc); 1819 hs20_eventlog_node(ctx, user, realm, session_id, 1820 "policy update response", 1821 ret); 1822 goto out; 1823 } 1824 1825 if (strcasecmp(req_reason, "User input completed") == 0) { 1826 if (devinfo) 1827 db_add_session_devinfo(ctx, session_id, devinfo); 1828 if (devdetail) 1829 db_add_session_devdetail(ctx, session_id, devdetail); 1830 ret = hs20_user_input_complete(ctx, user, realm, dmacc, 1831 session_id); 1832 hs20_eventlog_node(ctx, user, realm, session_id, 1833 "user input completed response", ret); 1834 goto out; 1835 } 1836 1837 if (strcasecmp(req_reason, "Certificate enrollment completed") == 0) { 1838 ret = hs20_cert_enroll_completed(ctx, user, realm, dmacc, 1839 session_id); 1840 hs20_eventlog_node(ctx, user, realm, session_id, 1841 "certificate enrollment response", ret); 1842 goto out; 1843 } 1844 1845 if (strcasecmp(req_reason, "Certificate enrollment failed") == 0) { 1846 ret = hs20_cert_enroll_failed(ctx, user, realm, dmacc, 1847 session_id); 1848 hs20_eventlog_node(ctx, user, realm, session_id, 1849 "certificate enrollment failed response", 1850 ret); 1851 goto out; 1852 } 1853 1854 debug_print(ctx, 1, "Unsupported requestReason '%s' user '%s'", 1855 req_reason, user); 1856 out: 1857 xml_node_get_attr_value_free(ctx->xml, req_reason_buf); 1858 xml_node_get_attr_value_free(ctx->xml, redirect_uri); 1859 if (devinfo) 1860 xml_node_free(ctx->xml, devinfo); 1861 if (devdetail) 1862 xml_node_free(ctx->xml, devdetail); 1863 return ret; 1864 } 1865 1866 1867 static xml_node_t * build_spp_exchange_complete(struct hs20_svc *ctx, 1868 const char *session_id, 1869 const char *status, 1870 const char *error_code) 1871 { 1872 xml_namespace_t *ns; 1873 xml_node_t *spp_node, *node; 1874 1875 spp_node = xml_node_create_root(ctx->xml, SPP_NS_URI, "spp", &ns, 1876 "sppExchangeComplete"); 1877 1878 1879 xml_node_add_attr(ctx->xml, spp_node, ns, "sppVersion", "1.0"); 1880 xml_node_add_attr(ctx->xml, spp_node, ns, "sessionID", session_id); 1881 xml_node_add_attr(ctx->xml, spp_node, ns, "sppStatus", status); 1882 1883 if (error_code) { 1884 node = xml_node_create(ctx->xml, spp_node, ns, "sppError"); 1885 xml_node_add_attr(ctx->xml, node, NULL, "errorCode", 1886 error_code); 1887 } 1888 1889 return spp_node; 1890 } 1891 1892 1893 static int add_subscription(struct hs20_svc *ctx, const char *session_id) 1894 { 1895 char *user, *realm, *pw, *pw_mm, *pps, *str; 1896 char *sql; 1897 int ret = -1; 1898 char *free_account; 1899 int free_acc; 1900 char *type; 1901 int cert = 0; 1902 char *cert_pem, *fingerprint; 1903 1904 user = db_get_session_val(ctx, NULL, NULL, session_id, "user"); 1905 realm = db_get_session_val(ctx, NULL, NULL, session_id, "realm"); 1906 pw = db_get_session_val(ctx, NULL, NULL, session_id, "password"); 1907 pw_mm = db_get_session_val(ctx, NULL, NULL, session_id, 1908 "machine_managed"); 1909 pps = db_get_session_val(ctx, NULL, NULL, session_id, "pps"); 1910 cert_pem = db_get_session_val(ctx, NULL, NULL, session_id, "cert_pem"); 1911 fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert"); 1912 type = db_get_session_val(ctx, NULL, NULL, session_id, "type"); 1913 if (type && strcmp(type, "cert") == 0) 1914 cert = 1; 1915 free(type); 1916 1917 if (!user || !realm || !pw) { 1918 debug_print(ctx, 1, "Could not find session info from DB for " 1919 "the new subscription"); 1920 goto out; 1921 } 1922 1923 free_account = db_get_osu_config_val(ctx, realm, "free_account"); 1924 free_acc = free_account && strcmp(free_account, user) == 0; 1925 free(free_account); 1926 1927 debug_print(ctx, 1, 1928 "New subscription: user='%s' realm='%s' free_acc=%d", 1929 user, realm, free_acc); 1930 debug_print(ctx, 1, "New subscription: pps='%s'", pps); 1931 1932 sql = sqlite3_mprintf("UPDATE eventlog SET user=%Q, realm=%Q WHERE " 1933 "sessionid=%Q AND (user='' OR user IS NULL)", 1934 user, realm, session_id); 1935 if (sql) { 1936 debug_print(ctx, 1, "DB: %s", sql); 1937 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 1938 debug_print(ctx, 1, "Failed to update eventlog in " 1939 "sqlite database: %s", 1940 sqlite3_errmsg(ctx->db)); 1941 } 1942 sqlite3_free(sql); 1943 } 1944 1945 if (free_acc) { 1946 hs20_eventlog(ctx, user, realm, session_id, 1947 "completed shared free account registration", 1948 NULL); 1949 ret = 0; 1950 goto out; 1951 } 1952 1953 sql = sqlite3_mprintf("INSERT INTO users(identity,realm,phase2," 1954 "methods,cert,cert_pem,machine_managed) VALUES " 1955 "(%Q,%Q,1,%Q,%Q,%Q,%d)", 1956 user, realm, cert ? "TLS" : "TTLS-MSCHAPV2", 1957 fingerprint ? fingerprint : "", 1958 cert_pem ? cert_pem : "", 1959 pw_mm && atoi(pw_mm) ? 1 : 0); 1960 if (sql == NULL) 1961 goto out; 1962 debug_print(ctx, 1, "DB: %s", sql); 1963 if (sqlite3_exec(ctx->db, sql, NULL, NULL, NULL) != SQLITE_OK) { 1964 debug_print(ctx, 1, "Failed to add user in sqlite database: %s", 1965 sqlite3_errmsg(ctx->db)); 1966 sqlite3_free(sql); 1967 goto out; 1968 } 1969 sqlite3_free(sql); 1970 1971 if (cert) 1972 ret = 0; 1973 else 1974 ret = update_password(ctx, user, realm, pw, 0); 1975 if (ret < 0) { 1976 sql = sqlite3_mprintf("DELETE FROM users WHERE identity=%Q AND " 1977 "realm=%Q AND phase2=1", 1978 user, realm); 1979 if (sql) { 1980 debug_print(ctx, 1, "DB: %s", sql); 1981 sqlite3_exec(ctx->db, sql, NULL, NULL, NULL); 1982 sqlite3_free(sql); 1983 } 1984 } 1985 1986 if (pps) 1987 db_update_mo_str(ctx, user, realm, "pps", pps); 1988 1989 str = db_get_session_val(ctx, NULL, NULL, session_id, "devinfo"); 1990 if (str) { 1991 db_update_mo_str(ctx, user, realm, "devinfo", str); 1992 free(str); 1993 } 1994 1995 str = db_get_session_val(ctx, NULL, NULL, session_id, "devdetail"); 1996 if (str) { 1997 db_update_mo_str(ctx, user, realm, "devdetail", str); 1998 free(str); 1999 } 2000 2001 if (ret == 0) { 2002 hs20_eventlog(ctx, user, realm, session_id, 2003 "completed subscription registration", NULL); 2004 } 2005 2006 out: 2007 free(user); 2008 free(realm); 2009 free(pw); 2010 free(pw_mm); 2011 free(pps); 2012 free(cert_pem); 2013 free(fingerprint); 2014 return ret; 2015 } 2016 2017 2018 static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx, 2019 xml_node_t *node, 2020 const char *user, 2021 const char *realm, 2022 const char *session_id, 2023 int dmacc) 2024 { 2025 char *status; 2026 xml_node_t *ret; 2027 char *val; 2028 enum hs20_session_operation oper; 2029 2030 status = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, 2031 "sppStatus"); 2032 if (status == NULL) { 2033 debug_print(ctx, 1, "No sppStatus attribute"); 2034 return NULL; 2035 } 2036 2037 debug_print(ctx, 1, "sppUpdateResponse: sppStatus: %s sessionID: %s", 2038 status, session_id); 2039 2040 val = db_get_session_val(ctx, user, realm, session_id, "operation"); 2041 if (!val) { 2042 debug_print(ctx, 1, 2043 "No session active for user: %s sessionID: %s", 2044 user, session_id); 2045 oper = NO_OPERATION; 2046 } else 2047 oper = atoi(val); 2048 2049 if (strcasecmp(status, "OK") == 0) { 2050 char *new_pw = NULL; 2051 2052 xml_node_get_attr_value_free(ctx->xml, status); 2053 2054 if (oper == USER_REMEDIATION) { 2055 new_pw = db_get_session_val(ctx, user, realm, 2056 session_id, "password"); 2057 if (new_pw == NULL || strlen(new_pw) == 0) { 2058 free(new_pw); 2059 ret = build_spp_exchange_complete( 2060 ctx, session_id, "Error occurred", 2061 "Other"); 2062 hs20_eventlog_node(ctx, user, realm, 2063 session_id, "No password " 2064 "had been assigned for " 2065 "session", ret); 2066 db_remove_session(ctx, user, realm, session_id); 2067 return ret; 2068 } 2069 oper = UPDATE_PASSWORD; 2070 } 2071 if (oper == UPDATE_PASSWORD) { 2072 if (!new_pw) { 2073 new_pw = db_get_session_val(ctx, user, realm, 2074 session_id, 2075 "password"); 2076 if (!new_pw) { 2077 db_remove_session(ctx, user, realm, 2078 session_id); 2079 return NULL; 2080 } 2081 } 2082 debug_print(ctx, 1, "Update user '%s' password in DB", 2083 user); 2084 if (update_password(ctx, user, realm, new_pw, dmacc) < 2085 0) { 2086 debug_print(ctx, 1, "Failed to update user " 2087 "'%s' password in DB", user); 2088 ret = build_spp_exchange_complete( 2089 ctx, session_id, "Error occurred", 2090 "Other"); 2091 hs20_eventlog_node(ctx, user, realm, 2092 session_id, "Failed to " 2093 "update database", ret); 2094 db_remove_session(ctx, user, realm, session_id); 2095 return ret; 2096 } 2097 hs20_eventlog(ctx, user, realm, 2098 session_id, "Updated user password " 2099 "in database", NULL); 2100 } 2101 if (oper == SUBSCRIPTION_REGISTRATION) { 2102 if (add_subscription(ctx, session_id) < 0) { 2103 debug_print(ctx, 1, "Failed to add " 2104 "subscription into DB"); 2105 ret = build_spp_exchange_complete( 2106 ctx, session_id, "Error occurred", 2107 "Other"); 2108 hs20_eventlog_node(ctx, user, realm, 2109 session_id, "Failed to " 2110 "update database", ret); 2111 db_remove_session(ctx, user, realm, session_id); 2112 return ret; 2113 } 2114 } 2115 if (oper == POLICY_REMEDIATION || oper == POLICY_UPDATE) { 2116 char *val; 2117 val = db_get_val(ctx, user, realm, "remediation", 2118 dmacc); 2119 if (val && strcmp(val, "policy") == 0) 2120 db_update_val(ctx, user, realm, "remediation", 2121 "", dmacc); 2122 free(val); 2123 } 2124 ret = build_spp_exchange_complete( 2125 ctx, session_id, 2126 "Exchange complete, release TLS connection", NULL); 2127 hs20_eventlog_node(ctx, user, realm, session_id, 2128 "Exchange completed", ret); 2129 db_remove_session(ctx, user, realm, session_id); 2130 return ret; 2131 } 2132 2133 ret = build_spp_exchange_complete(ctx, session_id, "Error occurred", 2134 "Other"); 2135 hs20_eventlog_node(ctx, user, realm, session_id, "Error occurred", ret); 2136 db_remove_session(ctx, user, realm, session_id); 2137 xml_node_get_attr_value_free(ctx->xml, status); 2138 return ret; 2139 } 2140 2141 2142 #define SPP_SESSION_ID_LEN 16 2143 2144 static char * gen_spp_session_id(void) 2145 { 2146 FILE *f; 2147 int i; 2148 char *session; 2149 2150 session = os_malloc(SPP_SESSION_ID_LEN * 2 + 1); 2151 if (session == NULL) 2152 return NULL; 2153 2154 f = fopen("/dev/urandom", "r"); 2155 if (f == NULL) { 2156 os_free(session); 2157 return NULL; 2158 } 2159 for (i = 0; i < SPP_SESSION_ID_LEN; i++) 2160 os_snprintf(session + i * 2, 3, "%02x", fgetc(f)); 2161 2162 fclose(f); 2163 return session; 2164 } 2165 2166 xml_node_t * hs20_spp_server_process(struct hs20_svc *ctx, xml_node_t *node, 2167 const char *auth_user, 2168 const char *auth_realm, int dmacc) 2169 { 2170 xml_node_t *ret = NULL; 2171 char *session_id; 2172 const char *op_name; 2173 char *xml_err; 2174 char fname[200]; 2175 2176 debug_dump_node(ctx, "received request", node); 2177 2178 if (!dmacc && auth_user && auth_realm) { 2179 char *real; 2180 real = db_get_val(ctx, auth_user, auth_realm, "identity", 0); 2181 if (!real) { 2182 real = db_get_val(ctx, auth_user, auth_realm, 2183 "identity", 1); 2184 if (real) 2185 dmacc = 1; 2186 } 2187 os_free(real); 2188 } 2189 2190 snprintf(fname, sizeof(fname), "%s/spp/spp.xsd", ctx->root_dir); 2191 if (xml_validate(ctx->xml, node, fname, &xml_err) < 0) { 2192 /* 2193 * We may not be able to extract the sessionID from invalid 2194 * input, but well, we can try. 2195 */ 2196 session_id = xml_node_get_attr_value_ns(ctx->xml, node, 2197 SPP_NS_URI, 2198 "sessionID"); 2199 debug_print(ctx, 1, 2200 "SPP message failed validation, xsd file: %s xml-error: %s", 2201 fname, xml_err); 2202 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2203 "SPP message failed validation", node); 2204 hs20_eventlog(ctx, auth_user, auth_realm, session_id, 2205 "Validation errors", xml_err); 2206 os_free(xml_err); 2207 xml_node_get_attr_value_free(ctx->xml, session_id); 2208 /* TODO: what to return here? */ 2209 ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 2210 "SppValidationError"); 2211 return ret; 2212 } 2213 2214 session_id = xml_node_get_attr_value_ns(ctx->xml, node, SPP_NS_URI, 2215 "sessionID"); 2216 if (session_id) { 2217 char *tmp; 2218 debug_print(ctx, 1, "Received sessionID %s", session_id); 2219 tmp = os_strdup(session_id); 2220 xml_node_get_attr_value_free(ctx->xml, session_id); 2221 if (tmp == NULL) 2222 return NULL; 2223 session_id = tmp; 2224 } else { 2225 session_id = gen_spp_session_id(); 2226 if (session_id == NULL) { 2227 debug_print(ctx, 1, "Failed to generate sessionID"); 2228 return NULL; 2229 } 2230 debug_print(ctx, 1, "Generated sessionID %s", session_id); 2231 } 2232 2233 op_name = xml_node_get_localname(ctx->xml, node); 2234 if (op_name == NULL) { 2235 debug_print(ctx, 1, "Could not get op_name"); 2236 return NULL; 2237 } 2238 2239 if (strcmp(op_name, "sppPostDevData") == 0) { 2240 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2241 "sppPostDevData received and validated", 2242 node); 2243 ret = hs20_spp_post_dev_data(ctx, node, auth_user, auth_realm, 2244 session_id, dmacc); 2245 } else if (strcmp(op_name, "sppUpdateResponse") == 0) { 2246 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2247 "sppUpdateResponse received and validated", 2248 node); 2249 ret = hs20_spp_update_response(ctx, node, auth_user, 2250 auth_realm, session_id, dmacc); 2251 } else { 2252 hs20_eventlog_node(ctx, auth_user, auth_realm, session_id, 2253 "Unsupported SPP message received and " 2254 "validated", node); 2255 debug_print(ctx, 1, "Unsupported operation '%s'", op_name); 2256 /* TODO: what to return here? */ 2257 ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 2258 "SppUnknownCommandError"); 2259 } 2260 os_free(session_id); 2261 2262 if (ret == NULL) { 2263 /* TODO: what to return here? */ 2264 ret = xml_node_create_root(ctx->xml, NULL, NULL, NULL, 2265 "SppInternalError"); 2266 } 2267 2268 return ret; 2269 } 2270 2271 2272 int hs20_spp_server_init(struct hs20_svc *ctx) 2273 { 2274 char fname[200]; 2275 ctx->db = NULL; 2276 snprintf(fname, sizeof(fname), "%s/AS/DB/eap_user.db", ctx->root_dir); 2277 if (sqlite3_open(fname, &ctx->db)) { 2278 printf("Failed to open sqlite database: %s\n", 2279 sqlite3_errmsg(ctx->db)); 2280 sqlite3_close(ctx->db); 2281 return -1; 2282 } 2283 2284 return 0; 2285 } 2286 2287 2288 void hs20_spp_server_deinit(struct hs20_svc *ctx) 2289 { 2290 sqlite3_close(ctx->db); 2291 ctx->db = NULL; 2292 } 2293