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