struct client_ctx *socket_listen(struct socket *s) { socklen_t len = sizeof(struct sockaddr_in); int fd = accept(s->fd, (struct sockaddr *) &cli.addr, &len); if (fd == -1) return 0; struct client_ctx *cc = calloc(sizeof(*cc), 1); cc->fd = fd; socket_clientaddr(cc); if (isbanned(cc)){ socket_puts(cc, "Banned lol\n"); socket_close(cc); free(cc); return 0; } return cc; }
void ident_check(struct descriptor_data *d, int pulse) { fd_set fd, efd; int rc, rmt_port, our_port, len; char user[256], *p; extern struct timeval null_time; extern int port; /* * Each pulse, this checks if the ident is ready to proceed to the * next state, by calling select to see if the socket is writeable * (connected) or readable (response waiting). */ switch (STATE(d)) { case CON_IDCONING: /* waiting for connect() to finish */ if (d->ident_sock != INVALID_SOCKET) { FD_ZERO(&fd); FD_ZERO(&efd); FD_SET(d->ident_sock, &fd); FD_SET(d->ident_sock, &efd); } if ((rc = select(d->ident_sock + 1, (fd_set *) 0, &fd, &efd, &null_time)) == 0) break; else if (rc < 0) { logerror("ident check select (conning)"); STATE(d) = CON_ASKNAME; break; } if (FD_ISSET(d->ident_sock, &efd)) { /* exception, such as failure to connect */ STATE(d) = CON_ASKNAME; break; } STATE(d) = CON_IDCONED; break; case CON_IDCONED: /* connected, write request */ sprintf(buf, "%d, %d\n\r", ntohs(d->peer_port), port); len = strlen(buf); #ifdef CIRCLE_WINDOWS if (send(d->ident_sock, buf, len, 0) < 0) { #else if (write(d->ident_sock, buf, len) != len) { if (errno != EPIPE) /* read end closed (no remote identd) */ #endif logerror("ident check write (conned)"); STATE(d) = CON_ASKNAME; break; } STATE(d) = CON_IDREADING; break; case CON_IDREADING: /* waiting to read */ if (d->ident_sock != INVALID_SOCKET) { FD_ZERO(&fd); FD_ZERO(&efd); FD_SET(d->ident_sock, &fd); FD_SET(d->ident_sock, &efd); } if ((rc = select(d->ident_sock + 1, &fd, (fd_set *) 0, &efd, &null_time)) == 0) break; else if (rc < 0) { logerror("ident check select (reading)"); STATE(d) = CON_ASKNAME; break; } if (FD_ISSET(d->ident_sock, &efd)) { STATE(d) = CON_ASKNAME; break; } STATE(d) = CON_IDREAD; break; case CON_IDREAD: /* read ready, get the info */ #ifdef CIRCLE_WINDOWS if ((len = recv(d->ident_sock, buf, sizeof(buf) - 1, 0)) < 0) #else if ((len = read(d->ident_sock, buf, sizeof(buf) - 1)) < 0) #endif logerror("ident check read (read)"); else { buf[len] = '\0'; if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &rmt_port, &our_port, user) != 3) { /* check if error or malformed */ if (sscanf(buf, "%u , %u : ERROR : %255s", &rmt_port, &our_port, user) == 3) { sprintf(buf2, "Ident error from %s: \"%s\"", d->hostIP, user); stderr_log(buf2); } else { /* strip off trailing newline */ for (p = buf + len - 1; p > buf && ISNEWL(*p); p--) ; p[1] = '\0'; sprintf(buf2, "Malformed ident response from %s: \"%s\"", d->hostIP, buf); stderr_log(buf2); } } else { len = HOST_LENGTH - strlen(d->hostIP); if (len > 0) { strncpy(buf2, user, len - 1); buf2[len - 1] = '\0'; strcpy(d->username, buf2); } /* if len <= 0, no space for username */ } } STATE(d) = CON_ASKNAME; break; case CON_ASKNAME: /* ident complete, ask for name */ /* close up the ident socket, if one is opened. */ if (d->ident_sock != INVALID_SOCKET) { close(d->ident_sock); d->ident_sock = INVALID_SOCKET; } d->idle_tics = 0; /* extra ban check */ if ((d->host[0] != '\0' && isbanned(d->host) == BAN_ALL) || isbanned(d->hostIP)) { if (d->host[0] != '\0') { sprintf(buf, "Connection attempt denied from [%s]", d->host); } else { sprintf(buf, "Connection attempt denied from [%s]", d->hostIP); } mudlog(buf, 'S', COM_IMMORT, TRUE); close_socket(d); return; } /* SEND_TO_Q("\x1B[2K\n\rBy what name do you wish to be known? ", d); */ STATE(d) = CON_GET_TERMTYPE; return; default: return; } /* * Print a dot every second so the user knows he hasn't been forgotten. * Allow the user to go on anyways after waiting IDENT_TIMEOUT seconds. */ if ((pulse % PASSES_PER_SEC) == 0) { SEND_TO_Q(".", d); if (d->idle_tics++ >= IDENT_TIMEOUT) STATE(d) = CON_ASKNAME; } } /* returns 1 if waiting for ident to complete, else 0 */ int waiting_for_ident(struct descriptor_data *d) { switch (STATE(d)) { case CON_IDCONING: case CON_IDCONED: case CON_IDREADING: case CON_IDREAD: case CON_ASKNAME: return 1; } return 0; }