static void server_job_signal(int sig ATTRIBUTE_UNUSED) { snd_pcm_direct_semaphore_down(server_job_dmix, DIRECT_IPC_SEM_CLIENT); server_cleanup(server_job_dmix); server_printf("DIRECT SERVER EXIT - SIGNAL\n"); _exit(EXIT_SUCCESS); }
static void server_job(snd_pcm_direct_t *dmix) { int ret, sck, i; int max = 128, current = 0; struct pollfd pfds[max + 1]; server_job_dmix = dmix; /* don't allow to be killed */ signal(SIGHUP, server_job_signal); signal(SIGQUIT, server_job_signal); signal(SIGTERM, server_job_signal); signal(SIGKILL, server_job_signal); /* close all files to free resources */ i = sysconf(_SC_OPEN_MAX); #ifdef SERVER_JOB_DEBUG while (--i >= 3) { #else while (--i >= 0) { #endif if (i != dmix->server_fd && i != dmix->hw_fd) close(i); } /* detach from parent */ setsid(); pfds[0].fd = dmix->server_fd; pfds[0].events = POLLIN | POLLERR | POLLHUP; server_printf("DIRECT SERVER STARTED\n"); while (1) { ret = poll(pfds, current + 1, 500); server_printf("DIRECT SERVER: poll ret = %i, revents[0] = 0x%x, errno = %i\n", ret, pfds[0].revents, errno); if (ret < 0) { if (errno == EINTR) continue; /* some error */ break; } if (ret == 0 || (pfds[0].revents & (POLLERR | POLLHUP))) { /* timeout or error? */ struct shmid_ds buf; snd_pcm_direct_semaphore_down(dmix, DIRECT_IPC_SEM_CLIENT); if (shmctl(dmix->shmid, IPC_STAT, &buf) < 0) { _snd_pcm_direct_shm_discard(dmix); snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); continue; } server_printf("DIRECT SERVER: nattch = %i\n", (int)buf.shm_nattch); if (buf.shm_nattch == 1) /* server is the last user, exit */ break; snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT); continue; } if (pfds[0].revents & POLLIN) { ret--; sck = accept(dmix->server_fd, 0, 0); if (sck >= 0) { server_printf("DIRECT SERVER: new connection %i\n", sck); if (current == max) { close(sck); } else { unsigned char buf = 'A'; pfds[current+1].fd = sck; pfds[current+1].events = POLLIN | POLLERR | POLLHUP; _snd_send_fd(sck, &buf, 1, dmix->hw_fd); server_printf("DIRECT SERVER: fd sent ok\n"); current++; } } } for (i = 0; i < current && ret > 0; i++) { struct pollfd *pfd = &pfds[i+1]; unsigned char cmd; server_printf("client %i revents = 0x%x\n", pfd->fd, pfd->revents); if (pfd->revents & (POLLERR | POLLHUP)) { ret--; close(pfd->fd); pfd->fd = -1; continue; } if (!(pfd->revents & POLLIN)) continue; ret--; if (read(pfd->fd, &cmd, 1) == 1) cmd = 0 /*process command */; } for (i = 0; i < current; i++) { if (pfds[i+1].fd < 0) { if (i + 1 != max) memcpy(&pfds[i+1], &pfds[i+2], sizeof(struct pollfd) * (max - i - 1)); current--; } } } server_cleanup(dmix); server_printf("DIRECT SERVER EXIT\n"); #ifdef SERVER_JOB_DEBUG close(0); close(1); close(2); #endif _exit(EXIT_SUCCESS); } int snd_pcm_direct_server_create(snd_pcm_direct_t *dmix) { int ret; dmix->server_fd = -1; ret = get_tmp_name(dmix->shmptr->socket_name, sizeof(dmix->shmptr->socket_name)); if (ret < 0) return ret; ret = make_local_socket(dmix->shmptr->socket_name, 1, dmix->ipc_perm, dmix->ipc_gid); if (ret < 0) return ret; dmix->server_fd = ret; ret = listen(dmix->server_fd, 4); if (ret < 0) { close(dmix->server_fd); return ret; } ret = fork(); if (ret < 0) { close(dmix->server_fd); return ret; } else if (ret == 0) { ret = fork(); if (ret == 0) server_job(dmix); _exit(EXIT_SUCCESS); } else { waitpid(ret, NULL, 0); } dmix->server_pid = ret; dmix->server = 1; return 0; }
int sserver_auth_protocol_connect(const struct protocol_interface *protocol, const char *auth_string) { CScramble scramble; char *tmp; int certonly; char *client_version = NULL; char keyfile[256]; const char *hostname = NULL; if (!strcmp (auth_string, "BEGIN SSL VERIFICATION REQUEST")) sserver_protocol_interface.verify_only = 1; else if (!strcmp (auth_string, "BEGIN SSL AUTH REQUEST")) sserver_protocol_interface.verify_only = 0; else return CVSPROTO_NOTME; write(current_server()->out_fd,SSERVER_INIT_STRING,sizeof(SSERVER_INIT_STRING)-1); if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","CertificatesOnly",keyfile,sizeof(keyfile))) certonly = atoi(keyfile); if(!CGlobalSettings::GetGlobalValue("cvsnt","PServer","ServerDnsName",keyfile,sizeof(keyfile))) hostname = keyfile; if(!ServerAuthenticate(hostname)) return CVSPROTO_AUTHFAIL; QueryContextAttributes(&contextHandle,SECPKG_ATTR_STREAM_SIZES,&secSizes); g_sslBufferInPos=g_sslBufferOutPos=0; g_sslBufferInLen=g_sslBufferOutLen=0; set_encrypted_channel(1); /* Error must go through us now */ PCERT_CONTEXT sc; PCCERT_CHAIN_CONTEXT pcc; CERT_SIMPLE_CHAIN *psc; CERT_CHAIN_PARA para = { sizeof(CERT_CHAIN_PARA) }; DWORD trust,rc; BOOL cert = FALSE; rc = QueryContextAttributes(&contextHandle,SECPKG_ATTR_REMOTE_CERT_CONTEXT,&sc); if(rc && rc!=SEC_E_NO_CREDENTIALS) server_error(1,"Couldn't get client certificate"); if(rc!=SEC_E_NO_CREDENTIALS) /* The client doesn't have to send us a cert. as cvs uses passwords normally */ { if(!CertGetCertificateChain(NULL, sc, NULL, NULL, ¶, 0, NULL, &pcc)) server_error(1,"Couldn't get client certificate chain"); psc = pcc->rgpChain[0]; trust = psc->TrustStatus.dwErrorStatus; if (trust) { if (trust & (CERT_TRUST_IS_PARTIAL_CHAIN | CERT_TRUST_IS_UNTRUSTED_ROOT)) server_error(1,"Client sent self signed certificate"); else if (trust & (CERT_TRUST_IS_NOT_TIME_VALID)) server_error(1,"Client certificate expired"); else server_error(1,"Client certificate verification failed - %08x",trust); } CertFreeCertificateChain(pcc); FreeContextBuffer(sc); cert = TRUE; } /* Get the three important pieces of information in order. */ /* See above comment about error handling. */ /* get version, if sent. 1.0 clients didn't have this handshake so we have to handle that. */ server_getline (protocol, &client_version, MAX_PATH); if(strncmp(client_version,"SSERVER-CLIENT ",15)) { sserver_protocol_interface.auth_repository = client_version; client_version = NULL; } else server_getline (protocol, &sserver_protocol_interface.auth_repository, MAX_PATH); server_getline (protocol, &sserver_protocol_interface.auth_username, MAX_PATH); server_getline (protocol, &sserver_protocol_interface.auth_password, MAX_PATH); if(client_version) free(client_version); client_version = NULL; /* ... and make sure the protocol ends on the right foot. */ /* See above comment about error handling. */ server_getline(protocol, &tmp, MAX_PATH); if (strcmp (tmp, sserver_protocol_interface.verify_only ? "END SSL VERIFICATION REQUEST" : "END SSL AUTH REQUEST") != 0) { server_printf ("bad auth protocol end: %s\n", tmp); free(tmp); return CVSPROTO_FAIL; } strcpy(sserver_protocol_interface.auth_password, scramble.Unscramble(sserver_protocol_interface.auth_password)); free(tmp); switch(certonly) { case 0: break; case 1: if(!cert) { server_error(0,"E Login requires a valid client certificate.\n"); return CVSPROTO_AUTHFAIL; } free(sserver_protocol_interface.auth_password); sserver_protocol_interface.auth_password = NULL; break; case 2: if(!cert) { server_error(0,"E Login requires a valid client certificate.\n"); return CVSPROTO_AUTHFAIL; } break; }; return CVSPROTO_SUCCESS; }
int sspi_auth_protocol_connect(const struct protocol_interface *protocol, const char *auth_string) { char *protocols; const char *proto; int fdin, fdout, fderr; int l; short len; char line[1024]; char buf[1024]; int first; if (!strcmp (auth_string, "BEGIN SSPI")) sspi_protocol_interface.verify_only = 0; else return CVSPROTO_NOTME; server_getline(protocol, &protocols, 1024); if(!protocols) { server_printf("Nope!\n"); return CVSPROTO_FAIL; } else if(strstr(protocols,"Negotiate")) proto="Negotiate"; else if(strstr(protocols,"NTLM")) proto="NTLM"; else { server_printf("Nope!\n"); return CVSPROTO_FAIL; } free(protocols); server_printf("%s\n",proto); /* We have negotiated NTLM */ if(run_command(winbindwrapper, &fdin, &fdout, &fderr)) return CVSPROTO_FAIL; first=1; do { read(current_server()->in_fd,&len,2); len=ntohs(len); l=read(current_server()->in_fd,buf,len); if(l<0) return CVSPROTO_FAIL; if(first) strcpy(line,"YR "); else strcpy(line,"KK "); first = 0; l=base64enc((unsigned char *)buf,(unsigned char *)line+3,len); strcat(line,"\n"); write(fdin, line, strlen(line)); l=read(fdout, line, sizeof(line)); if(l<0) return CVSPROTO_FAIL; line[l]='\0'; if(line[0]=='T' && line[1]=='T') { len=base64dec((unsigned char *)line+3,(unsigned char *)buf,l-4); base64enc((unsigned char *)buf,(unsigned char *)line+3,len); len=htons(len); write(current_server()->out_fd,&len,2); write(current_server()->out_fd,buf,ntohs(len)); } } while(line[0]=='T' && line[1]=='T'); if(line[0]!='A' || line[1]!='F') return CVSPROTO_FAIL; close(fdin); close(fdout); close(fderr); line[strlen(line)-1]='\0'; sspi_protocol_interface.auth_username = strdup(line+3); /* Get the repository details for checking */ server_getline (protocol, &sspi_protocol_interface.auth_repository, 4096); return CVSPROTO_SUCCESS; }