/* Split SCS atoms. Also save a copy of the base-64 encoded tag since * create_tag() will overwrite ats->b64_tag with the newly computed one, * and we still need it in tags_match() for comparison/validation. */ static int split_cookie (scs_t *ctx, const char *cookie, char tag[BASE64_LENGTH(SCS_TAG_MAX) + 1]) { size_t n; char cp[SCS_COOKIE_MAX] = { '\0' }, *pcp = &cp[0]; enum { DATA = 0, TSTAMP, TID, IV, TAG, NUM_ATOMS }; char *atoms[NUM_ATOMS + 1], **ap; /* Make a copy that we can freely clobber with strsep(). */ if (strlcpy(cp, cookie, sizeof cp) >= sizeof cp) { scs_set_error(ctx, SCS_ERR_FRAMING, "SCS_COOKIE_MAX exceeded"); return -1; } /* Put the expected 5 atoms on corresponding atoms[] slots, also doing * trivial integrity check (i.e. correct number and non-empty atoms.) */ for (n = 0, ap = atoms; (*ap = strsep(&pcp, "|")) != NULL; n++) { if (**ap == '\0' && n < NUM_ATOMS) { /* empty field */ scs_set_error(ctx, SCS_ERR_FRAMING, "field %zu is empty", n); return -1; } if (++ap > &atoms[NUM_ATOMS]) { scs_set_error(ctx, SCS_ERR_FRAMING, "too much atoms"); return -1; } } if (n != NUM_ATOMS) { scs_set_error(ctx, SCS_ERR_FRAMING, "got %zu atom(s), need 5", n); return -1; } /* Make a copy of the supplied authtag that can be compared with the * re-computed authtag. */ (void) strlcpy(tag, atoms[TAG], BASE64_LENGTH(SCS_TAG_MAX) + 1); /* Attach atoms to context. */ return attach_atoms(ctx, atoms[DATA], atoms[TSTAMP], atoms[TID], atoms[IV], atoms[TAG]); }
int handle_sec_auth_stats_cmd(sec_mod_st * sec, const CliStatsMsg * req) { client_entry_st *e; stats_st totals; if (req->sid.len != SID_SIZE) { seclog(sec, LOG_ERR, "auth session stats but with illegal sid size (%d)!", (int)req->sid.len); return -1; } e = find_client_entry(sec, req->sid.data); if (e == NULL) { char tmp[BASE64_LENGTH(SID_SIZE) + 1]; base64_encode((char *)req->sid.data, req->sid.len, (char *)tmp, sizeof(tmp)); seclog(sec, LOG_INFO, "session stats but with non-existing SID: %s", tmp); return -1; } if (e->status != PS_AUTH_COMPLETED) { seclog(sec, LOG_ERR, "session stats received in unauthenticated client %s "SESSION_STR"!", e->auth_info.username, e->auth_info.psid); return -1; } /* stats only increase */ if (req->bytes_in > e->stats.bytes_in) e->stats.bytes_in = req->bytes_in; if (req->bytes_out > e->stats.bytes_out) e->stats.bytes_out = req->bytes_out; if (req->uptime > e->stats.uptime) e->stats.uptime = req->uptime; if (req->has_discon_reason && req->discon_reason != 0) { e->discon_reason = req->discon_reason; } if (sec->perm_config->acct.amod == NULL || sec->perm_config->acct.amod->session_stats == NULL) return 0; stats_add_to(&totals, &e->stats, &e->saved_stats); if (req->remote_ip) strlcpy(e->auth_info.remote_ip, req->remote_ip, sizeof(e->auth_info.remote_ip)); if (req->ipv4) strlcpy(e->auth_info.ipv4, req->ipv4, sizeof(e->auth_info.ipv4)); if (req->ipv6) strlcpy(e->auth_info.ipv6, req->ipv6, sizeof(e->auth_info.ipv6)); sec->perm_config->acct.amod->session_stats(e->auth_type, e->auth_ctx, &e->auth_info, &totals); return 0; }
/** * \brief Decode the supplied SCS \p cookie-value. * * Decode the supplied SCS \p cookie string. If verification is successful, * the embedded state blob, whose length is found at \p *pstate_sz, is * returned to the caller. * * \param ctx An already initialized SCS context. * \param cookie The SCS cookie-value to be decoded. * \param pstate_sz The size in bytes of the decoded state blob as a * return argument. * * \return The decoded state blob on success, \c NULL if an error occurred. */ void *scs_decode (scs_t *ctx, const char *cookie, size_t *pstate_sz) { char tag[BASE64_LENGTH(SCS_TAG_MAX) + 1]; /* Check current keyset status. */ if (check_update_keyset(ctx)) return NULL; /* Cleanup the context. */ reset_atoms(&ctx->atoms); /* Get SCS atoms. */ if (split_cookie(ctx, cookie, tag)) return NULL; /* Handle the PDU validation process. */ return verify(ctx, tag, pstate_sz); }
static void tpl_init_base64(struct tpl *tpl) { // The rest of OSCam expects images to be base64 encoded and contain mime type. if(!template_is_image(tpl->tpl_type)) { return; } size_t b64_buf_len = 32 + BASE64_LENGTH(tpl->tpl_data_len); // Enough for base64 and 32 for header (data:XXX;base64,) char *b64_buf; if(!cs_malloc(&b64_buf, b64_buf_len)) { tpl->tpl_data = ""; tpl->tpl_data_len = 0; return; } int hdr_len = snprintf(b64_buf, b64_buf_len, "data:%s;base64,", template_get_mimetype(tpl->tpl_type)); base64_encode(tpl->tpl_data, tpl->tpl_data_len, b64_buf + hdr_len, b64_buf_len - hdr_len); tpl->tpl_data = tpl->extra_data = b64_buf; tpl->tpl_data_len = strlen(b64_buf); }
void websocket_info::parse_sec_key(request_impl const &req) { std::string const &key = req.header(WS_STR_SEC_WEBSOCKET_KEY); if (key.empty()) { throw std::runtime_error("can not find key in websocket request"); } enum { SHA_OUTPUT_SIZE = 20 }; unsigned char obuf[SHA_OUTPUT_SIZE]; std::string const key_data = key + WS_STR_SECRET_WORD; SHA1((const unsigned char*)key_data.c_str(), key_data.size(), obuf); BIO *b64 = BIO_new(BIO_f_base64()); if (NULL == b64) { throw std::bad_alloc(); } cleanup_bio cleaner(b64); BIO *bmem = BIO_new(BIO_s_mem()); if (NULL == bmem) { throw std::bad_alloc(); } cleaner.bio_ = b64 = BIO_push(b64, bmem); BIO_write(b64, obuf, sizeof(obuf)); BIO_flush(b64); BUF_MEM *bptr = NULL; BIO_get_mem_ptr(b64, &bptr); if (NULL == bptr || NULL == bptr->data || bptr->length != (BASE64_LENGTH(SHA_OUTPUT_SIZE) + 1)) { throw std::runtime_error("can not create accept data in websocket request"); } sec_data_.assign((const char*)bptr->data, bptr->length - 1); }
int main(int argc, char **argv) { xmppipe_state_t *state = NULL; xmpp_log_t *log = NULL; char *jid = NULL; char *pass = NULL; char *addr = NULL; u_int16_t port = 0; int flags = 0; int ch = 0; if (setvbuf(stdout, NULL, _IOLBF, 0) < 0) err(EXIT_FAILURE, "setvbuf"); state = xmppipe_calloc(1, sizeof(xmppipe_state_t)); xmppipe_next_state(state, XMPPIPE_S_CONNECTING); state->bufsz = 2049; state->poll = 10; state->keepalive = 60 * 1000; state->keepalive_limit = 3; state->sm_request_interval = 1; state->sm_fc = 15; state->sm_unacked = 5; state->room = xmppipe_roomname("stdout"); state->resource = xmppipe_strdup(XMPPIPE_RESOURCE); state->opt |= XMPPIPE_OPT_GROUPCHAT; jid = xmppipe_getenv("XMPPIPE_USERNAME"); pass = xmppipe_getenv("XMPPIPE_PASSWORD"); if (xmppipe_sandbox_init(state) < 0) err(EXIT_FAILURE, "sandbox failed"); while ( (ch = getopt_long(argc, argv, "a:b:c:dDeF:hI:k:K:o:P:p:r:sS:u:U:vx", long_options, NULL)) != -1) { switch (ch) { case 'u': /* username/jid */ free(jid); jid = xmppipe_strdup(optarg); break; case 'p': /* password */ free(pass); pass = xmppipe_strdup(optarg); break; case 'o': /* output/muc */ free(state->room); state->room = xmppipe_strdup(optarg); break; case 'a': { /* address:port */ char *p = NULL; free(addr); addr = xmppipe_strdup(optarg); p = strchr(addr, ':'); if (p) { *p++ = '\0'; port = xmppipe_strtonum(state, p, 0, 0xfffe); } } break; case 'r': free(state->resource); state->resource = xmppipe_strdup(optarg); break; case 'S': free(state->subject); state->subject = xmppipe_strdup(optarg); break; case 'v': state->verbose++; break; case 'F': if (strcmp(optarg, "text") == 0) state->format = XMPPIPE_FMT_TEXT; else if (strcmp(optarg, "csv") == 0) state->format = XMPPIPE_FMT_CSV; else usage(state); break; case 'x': state->encode = 1; break; case 'b': /* read buffer size */ state->bufsz = xmppipe_strtonum(state, optarg, 3, 0xfffe); break; case 'c': /* XEP-0198: stream management flow control */ state->sm_fc = xmppipe_strtonum(state, optarg, 0, 0xfffe); break; case 'I': /* XEP-0198: stream management request interval */ state->sm_request_interval = xmppipe_strtonum(state, optarg, 0, 0xfffe); break; case 'k': /* XEP-0199: XMPP ping keepalives */ state->sm_request_interval = xmppipe_strtonum(state, optarg, 0, 0xfffe) * 1000; break; case 'K': /* XEP-0199: number of keepalive without a reply */ state->keepalive_limit = xmppipe_strtonum(state, optarg, 1, 0xfffe); break; case 'P': /* poll delay */ state->poll = xmppipe_strtonum(state, optarg, 0, 0xfffe); break; case 'U': /* XEP-0198: stream management unacked requests */ state->sm_unacked = xmppipe_strtonum(state, optarg, 0, 0xfffe); break; case 'd': state->opt |= XMPPIPE_OPT_DISCARD; break; case 'D': state->opt |= XMPPIPE_OPT_DISCARD; state->opt |= XMPPIPE_OPT_DISCARD_TO_STDOUT; break; case 'e': state->opt |= XMPPIPE_OPT_EOF; break; case 's': state->opt |= XMPPIPE_OPT_SIGPIPE; break; case OPT_NO_TLS_VERIFY: flags |= XMPP_CONN_FLAG_TRUST_TLS; break; case OPT_CHAT: state->opt &= ~XMPPIPE_OPT_GROUPCHAT; break; case OPT_CHAT_MARKER: state->opt |= XMPPIPE_OPT_CHAT_MARKER; break; case 'h': default: usage(state); } } argc -= optind; argv += optind; if (argc > 0) { free(state->room); state->room = xmppipe_strdup(argv[0]); } if (jid == NULL) usage(state); if (state->encode && BASE64_LENGTH(state->bufsz) + 1 > 0xffff) usage(state); state->server = xmppipe_servername(jid); if (strchr(state->room, '@')) { state->out = xmppipe_strdup(state->room); state->mucjid = xmppipe_mucjid(state->out, state->resource); } else if (!(state->opt & XMPPIPE_OPT_GROUPCHAT)) { state->out = xmppipe_strdup(jid); } if (xmppipe_fmt_init() < 0) errx(EXIT_FAILURE, "xmppipe_fmt_init"); xmpp_initialize(); log = xmpp_get_default_logger(XMPP_LEVEL_DEBUG); state->ctx = xmpp_ctx_new(NULL, (state->verbose > 1 ? log : NULL)); if (state->ctx == NULL) errx(EXIT_FAILURE, "could not allocate context"); state->conn = xmpp_conn_new(state->ctx); if (state->conn == NULL) errx(EXIT_FAILURE, "could not allocate connection"); if (xmpp_conn_set_flags(state->conn, flags) < 0) errx(EXIT_FAILURE, "failed to set connection flags"); xmpp_conn_set_jid(state->conn, jid); xmpp_conn_set_pass(state->conn, pass); if (xmpp_connect_client(state->conn, addr, port, handle_connection, state) < 0) errx(EXIT_FAILURE, "connection failed"); if (xmppipe_connect_init(state) < 0) errx(EXIT_FAILURE, "XMPP handshake failed"); if (state->verbose) (void)fprintf(stderr, "sandbox: stdin: %s\n", XMPPIPE_SANDBOX); if (xmppipe_sandbox_stdin(state) < 0) err(EXIT_FAILURE, "sandbox failed"); if (xmppipe_stream_init(state) < 0) errx(EXIT_FAILURE, "enabling stream management failed"); if ( (state->opt & XMPPIPE_OPT_GROUPCHAT) && xmppipe_muc_init(state) < 0) errx(EXIT_FAILURE, "failed to join MUC"); if (xmppipe_presence_init(state) < 0) errx(EXIT_FAILURE, "publishing presence failed"); if ( (state->opt & XMPPIPE_OPT_GROUPCHAT) && state->subject) xmppipe_muc_subject(state, state->subject); event_loop(state); xmppipe_stream_close(state); (void)xmpp_conn_release(state->conn); xmpp_ctx_free(state->ctx); xmpp_shutdown(); return 0; }
static int handle_sec_auth_session_close(sec_mod_st *sec, int fd, const SecAuthSessionMsg *req) { client_entry_st *e; int ret; CliStatsMsg rep = CLI_STATS_MSG__INIT; if (req->sid.len != SID_SIZE) { seclog(sec, LOG_ERR, "auth session close but with illegal sid size (%d)!", (int)req->sid.len); return ERR_BAD_COMMAND; } e = find_client_entry(sec, req->sid.data); if (e == NULL) { char tmp[BASE64_LENGTH(SID_SIZE) + 1]; base64_encode((char *)req->sid.data, req->sid.len, (char *)tmp, sizeof(tmp)); seclog(sec, LOG_INFO, "session close but with non-existing SID: %s", tmp); return send_msg(e, fd, SM_CMD_AUTH_CLI_STATS, &rep, (pack_size_func) cli_stats_msg__get_packed_size, (pack_func) cli_stats_msg__pack); } if (e->status < PS_AUTH_COMPLETED) { seclog(sec, LOG_DEBUG, "session close received in unauthenticated client %s "SESSION_STR"!", e->auth_info.username, e->auth_info.psid); return send_msg(e, fd, SM_CMD_AUTH_CLI_STATS, &rep, (pack_size_func) cli_stats_msg__get_packed_size, (pack_func) cli_stats_msg__pack); } if (req->has_uptime && req->uptime > e->stats.uptime) { e->stats.uptime = req->uptime; } if (req->has_bytes_in && req->bytes_in > e->stats.bytes_in) { e->stats.bytes_in = req->bytes_in; } if (req->has_bytes_out && req->bytes_out > e->stats.bytes_out) { e->stats.bytes_out = req->bytes_out; } /* send reply */ rep.bytes_in = e->stats.bytes_in; rep.bytes_out = e->stats.bytes_out; rep.has_secmod_client_entries = 1; rep.secmod_client_entries = sec_mod_client_db_elems(sec); ret = send_msg(e, fd, SM_CMD_AUTH_CLI_STATS, &rep, (pack_size_func) cli_stats_msg__get_packed_size, (pack_func) cli_stats_msg__pack); if (ret < 0) { seclog(sec, LOG_ERR, "error in sending session stats"); return ERR_BAD_COMMAND; } /* save total stats */ stats_add_to(&e->saved_stats, &e->saved_stats, &e->stats); memset(&e->stats, 0, sizeof(e->stats)); expire_client_entry(sec, e); return 0; }
static int handle_sec_auth_session_open(sec_mod_st *sec, int fd, const SecAuthSessionMsg *req) { client_entry_st *e; void *lpool; int ret; SecAuthSessionReplyMsg rep = SEC_AUTH_SESSION_REPLY_MSG__INIT; if (req->sid.len != SID_SIZE) { seclog(sec, LOG_ERR, "auth session open but with illegal sid size (%d)!", (int)req->sid.len); return send_failed_session_open_reply(sec, fd); } e = find_client_entry(sec, req->sid.data); if (e == NULL) { char tmp[BASE64_LENGTH(SID_SIZE) + 1]; base64_encode((char *)req->sid.data, req->sid.len, (char *)tmp, sizeof(tmp)); seclog(sec, LOG_INFO, "session open but with non-existing SID: %s!", tmp); return send_failed_session_open_reply(sec, fd); } if (e->status != PS_AUTH_COMPLETED) { seclog(sec, LOG_ERR, "session open received in unauthenticated client %s "SESSION_STR"!", e->auth_info.username, e->auth_info.psid); return send_failed_session_open_reply(sec, fd); } if (e->time != -1 && time(0) > e->time + sec->config->cookie_timeout) { seclog(sec, LOG_ERR, "session expired; denied session for user '%s' "SESSION_STR, e->auth_info.username, e->auth_info.psid); e->status = PS_AUTH_FAILED; return send_failed_session_open_reply(sec, fd); } if (req->has_cookie == 0 || (req->cookie.len != e->cookie_size) || memcmp(req->cookie.data, e->cookie, e->cookie_size) != 0) { seclog(sec, LOG_ERR, "cookie error; denied session for user '%s' "SESSION_STR, e->auth_info.username, e->auth_info.psid); e->status = PS_AUTH_FAILED; return send_failed_session_open_reply(sec, fd); } if (req->ipv4) strlcpy(e->auth_info.ipv4, req->ipv4, sizeof(e->auth_info.ipv4)); if (req->ipv6) strlcpy(e->auth_info.ipv6, req->ipv6, sizeof(e->auth_info.ipv6)); if (sec->perm_config->acct.amod != NULL && sec->perm_config->acct.amod->open_session != NULL && e->session_is_open == 0) { ret = sec->perm_config->acct.amod->open_session(e->auth_type, e->auth_ctx, &e->auth_info, req->sid.data, req->sid.len); if (ret < 0) { e->status = PS_AUTH_FAILED; seclog(sec, LOG_INFO, "denied session for user '%s' "SESSION_STR, e->auth_info.username, e->auth_info.psid); return send_failed_session_open_reply(sec, fd); } else { e->session_is_open = 1; } } rep.reply = AUTH__REP__OK; lpool = talloc_new(e); if (lpool == NULL) { return ERR_BAD_COMMAND; /* we desync */ } if (sec->config_module && sec->config_module->get_sup_config) { ret = sec->config_module->get_sup_config(sec->config, e, &rep, lpool); if (ret < 0) { seclog(sec, LOG_ERR, "error reading additional configuration for '%s' "SESSION_STR, e->auth_info.username, e->auth_info.psid); talloc_free(lpool); return send_failed_session_open_reply(sec, fd); } } ret = send_msg(lpool, fd, SM_CMD_AUTH_SESSION_REPLY, &rep, (pack_size_func) sec_auth_session_reply_msg__get_packed_size, (pack_func) sec_auth_session_reply_msg__pack); if (ret < 0) { seclog(sec, LOG_ERR, "error in sending session reply"); return ERR_BAD_COMMAND; /* we desync */ } talloc_free(lpool); seclog(sec, LOG_INFO, "initiating session for user '%s' "SESSION_STR, e->auth_info.username, e->auth_info.psid); e->time = -1; e->in_use++; return 0; }
int post_common_handler(worker_st * ws, unsigned http_ver, const char *imsg) { int ret, size; char str_cookie[BASE64_LENGTH(ws->cookie_size)+1]; size_t str_cookie_size = sizeof(str_cookie); char msg[MAX_BANNER_SIZE + 32]; const char *success_msg_head; const char *success_msg_foot; unsigned success_msg_head_size; unsigned success_msg_foot_size; if (ws->req.user_agent_type == AGENT_OPENCONNECT_V3) { success_msg_head = ocv3_success_msg_head; success_msg_foot = ocv3_success_msg_foot; success_msg_head_size = sizeof(ocv3_success_msg_head)-1; success_msg_foot_size = sizeof(ocv3_success_msg_foot)-1; } else { success_msg_head = oc_success_msg_head; success_msg_foot = oc_success_msg_foot; success_msg_head_size = sizeof(oc_success_msg_head)-1; success_msg_foot_size = sizeof(oc_success_msg_foot)-1; } base64_encode((char *)ws->cookie, ws->cookie_size, (char *)str_cookie, str_cookie_size); /* reply */ oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 200 OK"); cstp_cork(ws); ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; ret = cstp_puts(ws, "Connection: Keep-Alive\r\n"); if (ret < 0) return -1; if (ws->selected_auth->type & AUTH_TYPE_GSSAPI && imsg != NULL && imsg[0] != 0) { ret = cstp_printf(ws, "WWW-Authenticate: Negotiate %s\r\n", imsg); if (ret < 0) return -1; } ret = cstp_puts(ws, "Content-Type: text/xml\r\n"); if (ret < 0) return -1; if (ws->config->banner) { size = snprintf(msg, sizeof(msg), "<banner>%s</banner>", ws->config->banner); if (size <= 0) return -1; /* snprintf() returns not a very useful value, so we need to recalculate */ size = strlen(msg); } else { msg[0] = 0; size = 0; } size += success_msg_head_size + success_msg_foot_size; ret = cstp_printf(ws, "Content-Length: %u\r\n", (unsigned)size); if (ret < 0) return -1; ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n"); if (ret < 0) return -1; ret = cstp_printf(ws, "Set-Cookie: webvpn=%s; Secure\r\n", str_cookie); if (ret < 0) return -1; #ifdef ANYCONNECT_CLIENT_COMPAT ret = cstp_puts(ws, "Set-Cookie: webvpnc=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; Secure\r\n"); if (ret < 0) return -1; if (ws->config->xml_config_file) { ret = cstp_printf(ws, "Set-Cookie: webvpnc=bu:/&p:t&iu:1/&sh:%s&lu:/+CSCOT+/translation-table?textdomain%%3DAnyConnect%%26type%%3Dmanifest&fu:profiles%%2F%s&fh:%s; path=/; Secure\r\n", ws->config->cert_hash, ws->config->xml_config_file, ws->config->xml_config_hash); } else { ret = cstp_printf(ws, "Set-Cookie: webvpnc=bu:/&p:t&iu:1/&sh:%s; path=/; Secure\r\n", ws->config->cert_hash); } if (ret < 0) return -1; #endif ret = cstp_printf(ws, "\r\n%s%s%s", success_msg_head, msg, success_msg_foot); if (ret < 0) return -1; ret = cstp_uncork(ws); if (ret < 0) return -1; return 0; }
int get_auth_handler2(worker_st * ws, unsigned http_ver, const char *pmsg) { int ret; char context[BASE64_LENGTH(SID_SIZE) + 1]; unsigned int i, j; str_st str; const char *login_msg_start; const char *login_msg_end; if (ws->req.user_agent_type == AGENT_OPENCONNECT_V3) { login_msg_start = OCV3_LOGIN_MSG_START; login_msg_end = ocv3_login_msg_end; } else { login_msg_start = OC_LOGIN_MSG_START; login_msg_end = oc_login_msg_end; } if (ws->selected_auth->type & AUTH_TYPE_GSSAPI && ws->auth_state < S_AUTH_COOKIE) { if (ws->req.authorization == NULL || ws->req.authorization_size == 0) return basic_auth_handler(ws, http_ver, NULL); else return post_auth_handler(ws, http_ver); } str_init(&str, ws); oclog(ws, LOG_HTTP_DEBUG, "HTTP sending: 200 OK"); cstp_cork(ws); ret = cstp_printf(ws, "HTTP/1.%u 200 OK\r\n", http_ver); if (ret < 0) return -1; if (ws->sid_set != 0) { base64_encode((char *)ws->sid, sizeof(ws->sid), (char *)context, sizeof(context)); ret = cstp_printf(ws, "Set-Cookie: webvpncontext=%s; Max-Age=%u; Secure\r\n", context, (unsigned)ws->config->cookie_timeout); if (ret < 0) return -1; oclog(ws, LOG_DEBUG, "sent sid: %s", context); } else { ret = cstp_puts(ws, "Set-Cookie: webvpncontext=; expires=Thu, 01 Jan 1970 22:00:00 GMT; path=/; Secure\r\n"); if (ret < 0) return -1; } ret = cstp_puts(ws, "Content-Type: text/xml\r\n"); if (ret < 0) { ret = -1; goto cleanup; } if (ws->auth_state == S_AUTH_REQ) { /* only ask password */ if (pmsg == NULL) pmsg = "Please enter your password"; ret = str_append_printf(&str, login_msg_start, pmsg); if (ret < 0) { ret = -1; goto cleanup; } ret = str_append_str(&str, login_msg_password); if (ret < 0) { ret = -1; goto cleanup; } ret = str_append_str(&str, login_msg_end); if (ret < 0) { ret = -1; goto cleanup; } } else { if (pmsg == NULL) pmsg = "Please enter your username"; /* ask for username and groups */ ret = str_append_printf(&str, login_msg_start, pmsg); if (ret < 0) { ret = -1; goto cleanup; } if (ws->selected_auth->type & AUTH_TYPE_USERNAME_PASS) { ret = str_append_str(&str, login_msg_user); if (ret < 0) { ret = -1; goto cleanup; } } if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE && ws->cert_auth_ok != 0) { ret = get_cert_info(ws); if (ret < 0) { ret = -1; oclog(ws, LOG_WARNING, "cannot obtain certificate information"); goto cleanup; } } /* send groups */ if (ws->config->group_list_size > 0 || ws->cert_groups_size > 0) { ret = str_append_str(&str, "<select name=\"group_list\" label=\"GROUP:\">\n"); if (ret < 0) { ret = -1; goto cleanup; } /* Several anyconnect clients (and openconnect) submit the group name * separately in that form. In that case they expect that we re-order * the list and we place the group they selected first. WTF! No respect * to server time. */ if (ws->groupname[0] != 0) { ret = append_group_str(ws, &str, ws->groupname); if (ret < 0) { ret = -1; goto cleanup; } } if (ws->config->default_select_group) { ret = str_append_printf(&str, "<option>%s</option>\n", ws->config->default_select_group); if (ret < 0) { ret = -1; goto cleanup; } } /* append any groups available in the certificate */ if (ws->selected_auth->type & AUTH_TYPE_CERTIFICATE && ws->cert_auth_ok != 0) { unsigned dup; for (i=0;i<ws->cert_groups_size;i++) { dup = 0; for (j=0;j<ws->config->group_list_size;j++) { if (strcmp(ws->cert_groups[i], ws->config->group_list[j]) == 0) { dup = 1; break; } } if (dup == 0 && ws->groupname[0] != 0 && strcmp(ws->groupname, ws->cert_groups[i]) == 0) dup = 1; if (dup != 0) continue; ret = str_append_printf(&str, "<option>%s</option>\n", ws->cert_groups[i]); if (ret < 0) { ret = -1; goto cleanup; } } } for (i=0;i<ws->config->group_list_size;i++) { if (ws->groupname[0] != 0 && strcmp(ws->groupname, ws->config->group_list[i]) == 0) continue; ret = append_group_idx(ws, &str, i); if (ret < 0) { ret = -1; goto cleanup; } } ret = str_append_str(&str, "</select>\n"); if (ret < 0) { ret = -1; goto cleanup; } } ret = str_append_str(&str, login_msg_end); if (ret < 0) { ret = -1; goto cleanup; } } ret = cstp_printf(ws, "Content-Length: %u\r\n", (unsigned int)str.length); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_puts(ws, "X-Transcend-Version: 1\r\n"); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_puts(ws, "\r\n"); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_send(ws, str.data, str.length); if (ret < 0) { ret = -1; goto cleanup; } ret = cstp_uncork(ws); if (ret < 0) { ret = -1; goto cleanup; } ret = 0; cleanup: str_clear(&str); return ret; }
/*Callback to process a metadata packet.*/ static void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata,void *client_data){ flacfile *flac; oe_enc_opt *inopt; (void)decoder; flac=(flacfile *)client_data; inopt=flac->inopt; switch(metadata->type){ case FLAC__METADATA_TYPE_STREAMINFO: flac->max_blocksize=metadata->data.stream_info.max_blocksize; inopt->rate=metadata->data.stream_info.sample_rate; inopt->channels=flac->channels=metadata->data.stream_info.channels; inopt->samplesize=metadata->data.stream_info.bits_per_sample; inopt->total_samples_per_channel= metadata->data.stream_info.total_samples; flac->block_buf=malloc( flac->max_blocksize*flac->channels*sizeof(*flac->block_buf)); flac->block_buf_pos=0; flac->block_buf_len=0; break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: { FLAC__StreamMetadata_VorbisComment_Entry *comments; FLAC__uint32 num_comments; FLAC__uint32 i; double reference_loudness; double album_gain; double track_gain; double gain; int saw_album_gain; int saw_track_gain; char *saved_locale; if(!inopt->copy_comments)break; num_comments=metadata->data.vorbis_comment.num_comments; comments=metadata->data.vorbis_comment.comments; saw_album_gain=saw_track_gain=0; album_gain=track_gain=0; /*The default reference loudness for ReplayGain is 89.0 dB*/ reference_loudness=89; /*The code below uses strtod for the gain tags, so make sure the locale is C*/ saved_locale=setlocale(LC_NUMERIC,"C"); for(i=0;i<num_comments;i++){ char *entry; char *end; entry=(char *)comments[i].entry; /*Check for ReplayGain tags. Parse the ones we have R128 equivalents for, and skip the others.*/ if(oi_strncasecmp(entry,"REPLAYGAIN_REFERENCE_LOUDNESS=",30)==0){ gain=strtod(entry+30,&end); if(end<=entry+30){ fprintf(stderr,_("WARNING: Invalid ReplayGain tag: %s\n"),entry); } else reference_loudness=gain; continue; } if(oi_strncasecmp(entry,"REPLAYGAIN_ALBUM_GAIN=",22)==0){ gain=strtod(entry+22,&end); if(end<=entry+22){ fprintf(stderr,_("WARNING: Invalid ReplayGain tag: %s\n"),entry); } else{ album_gain=gain; saw_album_gain=1; } continue; } if(oi_strncasecmp(entry,"REPLAYGAIN_TRACK_GAIN=",22)==0){ gain=strtod(entry+22,&end); if(end<entry+22){ fprintf(stderr,_("WARNING: Invalid ReplayGain tag: %s\n"),entry); } else{ track_gain=gain; saw_track_gain=1; } continue; } if(oi_strncasecmp(entry,"REPLAYGAIN_ALBUM_PEAK=",22)==0 ||oi_strncasecmp(entry,"REPLAYGAIN_TRACK_PEAK=",22)==0){ continue; } if(!strchr(entry,'=')){ fprintf(stderr,_("WARNING: Invalid comment: %s\n"),entry); fprintf(stderr, _("Discarding comment not in the form name=value\n")); continue; } comment_add(&inopt->comments,&inopt->comments_length,NULL,entry); } setlocale(LC_NUMERIC,saved_locale); /*Set the header gain to the album gain after converting to the R128 reference level.*/ if(saw_album_gain){ gain=256*(album_gain+(84-reference_loudness))+0.5; inopt->gain=gain<-32768?-32768:gain<32767?(int)floor(gain):32767; } /*If there was a track gain, then add an equivalent R128 tag for that.*/ if(saw_track_gain){ char track_gain_buf[7]; int track_gain_val; gain=256*(track_gain-album_gain)+0.5; track_gain_val=gain<-32768?-32768:gain<32767?(int)floor(gain):32767; sprintf(track_gain_buf,"%i",track_gain_val); comment_add(&inopt->comments,&inopt->comments_length, "R128_TRACK_GAIN",track_gain_buf); } } break; case FLAC__METADATA_TYPE_PICTURE: { char *buf; char *b64; size_t mime_type_length; size_t description_length; size_t buf_sz; size_t b64_sz; size_t offs; mime_type_length=strlen(metadata->data.picture.mime_type); description_length=strlen((char *)metadata->data.picture.description); buf_sz=32+mime_type_length+description_length +metadata->data.picture.data_length; buf=(char *)malloc(buf_sz); offs=0; WRITE_U32_BE(buf+offs,metadata->data.picture.type); offs+=4; WRITE_U32_BE(buf+offs,(FLAC__uint32)mime_type_length); offs+=4; memcpy(buf+offs,metadata->data.picture.mime_type,mime_type_length); offs+=mime_type_length; WRITE_U32_BE(buf+offs,(FLAC__uint32)description_length); offs+=4; memcpy(buf+offs,metadata->data.picture.description,description_length); offs+=description_length; WRITE_U32_BE(buf+offs,metadata->data.picture.width); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.height); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.depth); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.colors); offs+=4; WRITE_U32_BE(buf+offs,metadata->data.picture.data_length); offs+=4; memcpy(buf+offs,metadata->data.picture.data, metadata->data.picture.data_length); b64_sz=BASE64_LENGTH(buf_sz)+1; b64=(char *)malloc(b64_sz); base64_encode(b64,buf,buf_sz); free(buf); comment_add(&inopt->comments,&inopt->comments_length, "METADATA_BLOCK_PICTURE",b64); free(b64); } break; default: break; } }
static int create_tag (scs_t *ctx, scs_keyset_t *ks, int skip_encoding) { size_t i; scs_atoms_t *ats = &ctx->atoms; enum { NUM_ATOMS = 4 }; struct { const char *id; uint8_t *raw; char *enc; size_t raw_sz, enc_sz; } A[NUM_ATOMS] = { { "SCS DATA", ats->data, ats->b64_data, ats->data_sz, BASE64_LENGTH(ats->data_sz) }, { "SCS TSTAMP", (uint8_t *) ats->tstamp, ats->b64_tstamp, strlen(ats->tstamp), sizeof(ats->b64_tstamp) }, { "SCS TID", (uint8_t *) ks->tid, ats->b64_tid, strlen(ks->tid), sizeof(ats->b64_tid) }, { "SCS IV", ats->iv, ats->b64_iv, ks->block_sz, BASE64_LENGTH(ks->block_sz) } }; /* If requested, create Base-64 encoded versions of atoms. */ if (!skip_encoding) { for (i = 0; i < NUM_ATOMS; ++i) { if (base64url_encode(A[i].raw, A[i].raw_sz, A[i].enc, &A[i].enc_sz)) { scs_set_error(ctx, SCS_ERR_ENCODE, "%s encode failed", A[i].id); return -1; } } } /* Create auth tag. */ if (D.tag(ctx, ks)) return -1; size_t b64_tag = sizeof ats->b64_tag; /* Base-64 encode the auth tag. */ if (base64url_encode(ats->tag, ats->tag_sz, ats->b64_tag, &b64_tag)) { scs_set_error(ctx, SCS_ERR_ENCODE, "tag encode failed"); return -1; } return 0; }
static const char *do_cookie (scs_t *ctx, char cookie[SCS_COOKIE_MAX]); /* Decode support. */ static scs_keyset_t *retr_keyset (scs_t *ctx); static int attach_atoms (scs_t *ctx, const char *b64_data, const char *b64_tstamp, const char *b64_tid, const char *b64_iv, const char *b64_tag); static int decode_atoms (scs_t *ctx, scs_keyset_t *ks); static int tags_match (scs_t *ctx, const char *tag); static int tstamp_ok (scs_t *ctx); static int optional_inflate (scs_t *ctx, scs_keyset_t *ks); static int decrypt_state (scs_t *ctx, scs_keyset_t *ks); static int remove_pad (scs_t *ctx); static int do_inflate (scs_t *ctx); static int split_cookie (scs_t *ctx, const char *cookie, char tag[BASE64_LENGTH(SCS_TAG_MAX) + 1]); static void *verify (scs_t *ctx, const char *tag, size_t *pstate_sz); /* Auto refresh support. */ static int check_update_keyset (scs_t *ctx); static int update_last_refresh (scs_t *ctx, time_t now); /** * \defgroup scs SCS * \{ * TODO * * \section init Initialization * TODO * * \section encode Encoding