00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #include <errno.h>
00068 #include <signal.h>
00069 #include <unistd.h>
00070
00071 #include "gwlib/gwlib.h"
00072 #include "bearerbox.h"
00073
00074
00075
00076 extern volatile sig_atomic_t bb_status;
00077
00078
00079
00080 static volatile sig_atomic_t httpadmin_running;
00081
00082 static long ha_port;
00083 static Octstr *ha_interface;
00084 static Octstr *ha_password;
00085 static Octstr *ha_status_pw;
00086 static Octstr *ha_allow_ip;
00087 static Octstr *ha_deny_ip;
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 static Octstr *httpd_check_authorization(List *cgivars, int status)
00099 {
00100 Octstr *password;
00101 static double sleep = 0.01;
00102
00103 password = http_cgi_variable(cgivars, "password");
00104
00105 if (status) {
00106 if (ha_status_pw == NULL)
00107 return NULL;
00108
00109 if (password == NULL)
00110 goto denied;
00111
00112 if (octstr_compare(password, ha_password)!=0
00113 && octstr_compare(password, ha_status_pw)!=0)
00114 goto denied;
00115 }
00116 else {
00117 if (password == NULL || octstr_compare(password, ha_password)!=0)
00118 goto denied;
00119 }
00120 sleep = 0.0;
00121 return NULL;
00122 denied:
00123 gwthread_sleep(sleep);
00124 sleep += 1.0;
00125
00126 return octstr_create("Denied");
00127 }
00128
00129
00130
00131
00132 static Octstr *httpd_check_status(void)
00133 {
00134 if (bb_status == BB_SHUTDOWN || bb_status == BB_DEAD)
00135 return octstr_create("Avalanche has already started, too late to "
00136 "save the sheeps");
00137 return NULL;
00138 }
00139
00140 static Octstr *httpd_status(List *cgivars, int status_type)
00141 {
00142 Octstr *reply;
00143 if ((reply = httpd_check_authorization(cgivars, 1))!= NULL) return reply;
00144 return bb_print_status(status_type);
00145 }
00146
00147 static Octstr *httpd_store_status(List *cgivars, int status_type)
00148 {
00149 Octstr *reply;
00150 if ((reply = httpd_check_authorization(cgivars, 1))!= NULL) return reply;
00151 return store_status(status_type);
00152 }
00153
00154 static Octstr *httpd_loglevel(List *cgivars, int status_type)
00155 {
00156 Octstr *reply;
00157 Octstr *level;
00158 int new_loglevel;
00159
00160 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00161 if ((reply = httpd_check_status())!= NULL) return reply;
00162
00163
00164 level = http_cgi_variable(cgivars, "level");
00165 if (level) {
00166 new_loglevel = atoi(octstr_get_cstr(level));
00167 log_set_log_level(new_loglevel);
00168 return octstr_format("log-level set to %d", new_loglevel);
00169 }
00170 else {
00171 return octstr_create("New level not given");
00172 }
00173 }
00174
00175 static Octstr *httpd_shutdown(List *cgivars, int status_type)
00176 {
00177 Octstr *reply;
00178 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00179 if (bb_status == BB_SHUTDOWN)
00180 bb_status = BB_DEAD;
00181 else {
00182 bb_shutdown();
00183 gwthread_wakeup(MAIN_THREAD_ID);
00184 }
00185 return octstr_create("Bringing system down");
00186 }
00187
00188 static Octstr *httpd_isolate(List *cgivars, int status_type)
00189 {
00190 Octstr *reply;
00191 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00192 if ((reply = httpd_check_status())!= NULL) return reply;
00193
00194 if (bb_isolate() == -1)
00195 return octstr_create("Already isolated");
00196 else
00197 return octstr_create(GW_NAME " isolated from message providers");
00198 }
00199
00200 static Octstr *httpd_suspend(List *cgivars, int status_type)
00201 {
00202 Octstr *reply;
00203 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00204 if ((reply = httpd_check_status())!= NULL) return reply;
00205
00206 if (bb_suspend() == -1)
00207 return octstr_create("Already suspended");
00208 else
00209 return octstr_create(GW_NAME " suspended");
00210 }
00211
00212 static Octstr *httpd_resume(List *cgivars, int status_type)
00213 {
00214 Octstr *reply;
00215 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00216 if ((reply = httpd_check_status())!= NULL) return reply;
00217
00218 if (bb_resume() == -1)
00219 return octstr_create("Already running");
00220 else
00221 return octstr_create("Running resumed");
00222 }
00223
00224 static Octstr *httpd_restart(List *cgivars, int status_type)
00225 {
00226 Octstr *reply;
00227 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00228 if ((reply = httpd_check_status())!= NULL) return reply;
00229
00230 if (bb_status == BB_SHUTDOWN) {
00231 bb_status = BB_DEAD;
00232 gwthread_wakeup_all();
00233 return octstr_create("Trying harder to restart");
00234 }
00235 bb_restart();
00236 return octstr_create("Restarting.....");
00237 }
00238
00239 static Octstr *httpd_flush_dlr(List *cgivars, int status_type)
00240 {
00241 Octstr *reply;
00242 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00243 if ((reply = httpd_check_status())!= NULL) return reply;
00244
00245 if (bb_flush_dlr() == -1)
00246 return octstr_create("Suspend " GW_NAME " before trying to flush DLR queue");
00247 else
00248 return octstr_create("DLR queue flushed");
00249 }
00250
00251 static Octstr *httpd_stop_smsc(List *cgivars, int status_type)
00252 {
00253 Octstr *reply;
00254 Octstr *smsc;
00255 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00256 if ((reply = httpd_check_status())!= NULL) return reply;
00257
00258
00259 smsc = http_cgi_variable(cgivars, "smsc");
00260 if (smsc) {
00261 if (bb_stop_smsc(smsc) == -1)
00262 return octstr_format("Could not shut down smsc-id `%s'", octstr_get_cstr(smsc));
00263 else
00264 return octstr_format("SMSC `%s' shut down", octstr_get_cstr(smsc));
00265 } else
00266 return octstr_create("SMSC id not given");
00267 }
00268
00269 static Octstr *httpd_restart_smsc(List *cgivars, int status_type)
00270 {
00271 Octstr *reply;
00272 Octstr *smsc;
00273 if ((reply = httpd_check_authorization(cgivars, 0))!= NULL) return reply;
00274 if ((reply = httpd_check_status())!= NULL) return reply;
00275
00276
00277 smsc = http_cgi_variable(cgivars, "smsc");
00278 if (smsc) {
00279 if (bb_restart_smsc(smsc) == -1)
00280 return octstr_format("Could not re-start smsc-id `%s'", octstr_get_cstr(smsc));
00281 else
00282 return octstr_format("SMSC `%s' re-started", octstr_get_cstr(smsc));
00283 } else
00284 return octstr_create("SMSC id not given");
00285 }
00286
00287
00288 static struct httpd_command {
00289 const char *command;
00290 Octstr * (*function)(List *cgivars, int status_type);
00291 } httpd_commands[] = {
00292 { "status", httpd_status },
00293 { "store-status", httpd_store_status },
00294 { "log-level", httpd_loglevel },
00295 { "shutdown", httpd_shutdown },
00296 { "suspend", httpd_suspend },
00297 { "isolate", httpd_isolate },
00298 { "resume", httpd_resume },
00299 { "restart", httpd_restart },
00300 { "flush-dlr", httpd_flush_dlr },
00301 { "stop-smsc", httpd_stop_smsc },
00302 { "start-smsc", httpd_restart_smsc },
00303 { NULL , NULL }
00304 };
00305
00306 static void httpd_serve(HTTPClient *client, Octstr *ourl, List *headers,
00307 Octstr *body, List *cgivars)
00308 {
00309 Octstr *reply, *final_reply, *url;
00310 char *content_type;
00311 char *header, *footer;
00312 int status_type;
00313 int i;
00314 long pos;
00315
00316 reply = final_reply = NULL;
00317 url = octstr_duplicate(ourl);
00318
00319
00320
00321 if (http_type_accepted(headers, "text/vnd.wap.wml")) {
00322 status_type = BBSTATUS_WML;
00323 content_type = "text/vnd.wap.wml";
00324 }
00325 else if (http_type_accepted(headers, "text/html")) {
00326 status_type = BBSTATUS_HTML;
00327 content_type = "text/html";
00328 }
00329 else if (http_type_accepted(headers, "text/xml")) {
00330 status_type = BBSTATUS_XML;
00331 content_type = "text/xml";
00332 } else {
00333 status_type = BBSTATUS_TEXT;
00334 content_type = "text/plain";
00335 }
00336
00337
00338 pos = octstr_search(url, octstr_imm("/cgi-bin/"), 0);
00339 if (pos != -1)
00340 octstr_delete(url, pos, 9);
00341 else if (octstr_get_char(url, 0) == '/')
00342 octstr_delete(url, 0, 1);
00343
00344
00345 pos = octstr_search_char(url, '.', 0);
00346 if (pos != -1) {
00347 Octstr *tmp = octstr_copy(url, pos+1, octstr_len(url) - pos - 1);
00348 octstr_delete(url, pos, octstr_len(url) - pos);
00349
00350 if (octstr_str_compare(tmp, "txt") == 0)
00351 status_type = BBSTATUS_TEXT;
00352 else if (octstr_str_compare(tmp, "html") == 0)
00353 status_type = BBSTATUS_HTML;
00354 else if (octstr_str_compare(tmp, "xml") == 0)
00355 status_type = BBSTATUS_XML;
00356 else if (octstr_str_compare(tmp, "wml") == 0)
00357 status_type = BBSTATUS_WML;
00358
00359 octstr_destroy(tmp);
00360 }
00361
00362 for (i=0; httpd_commands[i].command != NULL; i++) {
00363 if (octstr_str_compare(url, httpd_commands[i].command) == 0) {
00364 reply = httpd_commands[i].function(cgivars, status_type);
00365 break;
00366 }
00367 }
00368
00369
00370 if (httpd_commands[i].command == NULL) {
00371 char *lb = bb_status_linebreak(status_type);
00372 reply = octstr_format("Unknown command `%S'.%sPossible commands are:%s",
00373 ourl, lb, lb);
00374 for (i=0; httpd_commands[i].command != NULL; i++)
00375 octstr_format_append(reply, "%s%s", httpd_commands[i].command, lb);
00376 }
00377
00378 gw_assert(reply != NULL);
00379
00380 if (status_type == BBSTATUS_HTML) {
00381 header = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n"
00382 "<html>\n<title>" GW_NAME "</title>\n<body>\n<p>";
00383 footer = "</p>\n</body></html>\n";
00384 content_type = "text/html";
00385 } else if (status_type == BBSTATUS_WML) {
00386 header = "<?xml version=\"1.0\"?>\n"
00387 "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" "
00388 "\"http://www.wapforum.org/DTD/wml_1.1.xml\">\n"
00389 "\n<wml>\n <card>\n <p>";
00390 footer = " </p>\n </card>\n</wml>\n";
00391 content_type = "text/vnd.wap.wml";
00392 } else if (status_type == BBSTATUS_XML) {
00393 header = "<?xml version=\"1.0\"?>\n"
00394 "<gateway>\n";
00395 footer = "</gateway>\n";
00396 } else {
00397 header = "";
00398 footer = "";
00399 content_type = "text/plain";
00400 }
00401 final_reply = octstr_create(header);
00402 octstr_append(final_reply, reply);
00403 octstr_append_cstr(final_reply, footer);
00404
00405
00406
00407 http_destroy_headers(headers);
00408 headers = gwlist_create();
00409 http_header_add(headers, "Content-Type", content_type);
00410
00411 http_send_reply(client, HTTP_OK, headers, final_reply);
00412
00413 octstr_destroy(url);
00414 octstr_destroy(ourl);
00415 octstr_destroy(body);
00416 octstr_destroy(reply);
00417 octstr_destroy(final_reply);
00418 http_destroy_headers(headers);
00419 http_destroy_cgiargs(cgivars);
00420 }
00421
00422 static void httpadmin_run(void *arg)
00423 {
00424 HTTPClient *client;
00425 Octstr *ip, *url, *body;
00426 List *headers, *cgivars;
00427
00428 while(bb_status != BB_DEAD) {
00429 if (bb_status == BB_SHUTDOWN)
00430 bb_shutdown();
00431 client = http_accept_request(ha_port, &ip, &url, &headers, &body,
00432 &cgivars);
00433 if (client == NULL)
00434 break;
00435 if (is_allowed_ip(ha_allow_ip, ha_deny_ip, ip) == 0) {
00436 info(0, "HTTP admin tried from denied host <%s>, disconnected",
00437 octstr_get_cstr(ip));
00438 http_close_client(client);
00439 continue;
00440 }
00441 httpd_serve(client, url, headers, body, cgivars);
00442 octstr_destroy(ip);
00443 }
00444
00445 httpadmin_running = 0;
00446 }
00447
00448
00449
00450
00451
00452
00453
00454 int httpadmin_start(Cfg *cfg)
00455 {
00456 CfgGroup *grp;
00457 int ssl = 0;
00458 #ifdef HAVE_LIBSSL
00459 Octstr *ssl_server_cert_file;
00460 Octstr *ssl_server_key_file;
00461 #endif
00462
00463 if (httpadmin_running) return -1;
00464
00465
00466 grp = cfg_get_single_group(cfg, octstr_imm("core"));
00467 if (cfg_get_integer(&ha_port, grp, octstr_imm("admin-port")) == -1)
00468 panic(0, "Missing admin-port variable, cannot start HTTP admin");
00469
00470 ha_interface = cfg_get(grp, octstr_imm("admin-interface"));
00471 ha_password = cfg_get(grp, octstr_imm("admin-password"));
00472 if (ha_password == NULL)
00473 panic(0, "You MUST set HTTP admin-password");
00474
00475 ha_status_pw = cfg_get(grp, octstr_imm("status-password"));
00476
00477 ha_allow_ip = cfg_get(grp, octstr_imm("admin-allow-ip"));
00478 ha_deny_ip = cfg_get(grp, octstr_imm("admin-deny-ip"));
00479
00480 #ifdef HAVE_LIBSSL
00481 cfg_get_bool(&ssl, grp, octstr_imm("admin-port-ssl"));
00482
00483
00484
00485
00486
00487
00488 ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file"));
00489 ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file"));
00490 if (ssl_server_cert_file != NULL && ssl_server_key_file != NULL) {
00491
00492
00493
00494
00495
00496
00497 } else if (ssl) {
00498 panic(0, "You MUST specify cert and key files within core group for SSL-enabled HTTP servers!");
00499 }
00500
00501 octstr_destroy(ssl_server_cert_file);
00502 octstr_destroy(ssl_server_key_file);
00503 #endif
00504
00505 http_open_port_if(ha_port, ssl, ha_interface);
00506
00507 if (gwthread_create(httpadmin_run, NULL) == -1)
00508 panic(0, "Failed to start a new thread for HTTP admin");
00509
00510 httpadmin_running = 1;
00511 return 0;
00512 }
00513
00514
00515 void httpadmin_stop(void)
00516 {
00517 http_close_all_ports();
00518 gwthread_join_every(httpadmin_run);
00519 octstr_destroy(ha_interface);
00520 octstr_destroy(ha_password);
00521 octstr_destroy(ha_status_pw);
00522 octstr_destroy(ha_allow_ip);
00523 octstr_destroy(ha_deny_ip);
00524 ha_password = NULL;
00525 ha_status_pw = NULL;
00526 ha_allow_ip = NULL;
00527 ha_deny_ip = NULL;
00528 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.