void imcsplay(int argc, char **argv) { setlinebuf(stdout); if (argc < 5 || argc > 7) usage(); char mecolor = '?'; int megame = 0; switch(argv[2][0]) { case 'O': switch(argv[2][1]) { case 'W': case 'B': case '?': mecolor = argv[2][1]; break; default: usage(); } break; case 'A': { char ch = argv[2][1]; if (isdigit(ch)) { megame = atoi(&argv[2][1]); } else if (ch == 'W' || ch == 'B') { mecolor = ch; megame = atoi(&argv[2][2]); } else { usage(); } if (megame <= 0) usage(); break; } default: usage(); } char *meuser = argv[3]; char *mepassword = argv[4]; char *host = "imcs.svcs.cs.pdx.edu"; if (argc > 5) host = argv[5]; int port = 3589; if (argc > 6) { port = atoi(argv[6]); if (port <= 0) usage(); } FILE *nf = netopen(host, port); setlinebuf(nf); startlog(); char *greeting = expectcmd(nf, 1, 100, 0); (void) strtok(greeting, " "); char *pgm = strtok(0, " "); assert(!strcmp(pgm, "imcs")); char *version = strtok(0, " \r\n"); if(strcmp(version, "2.5")) { fprintf(stderr, "got unexpected imcs version %s\n", version); exit(1); } sendcmd(nf, "me %s %s", meuser, mepassword); (void) expectcmd(nf, 1, 201, 0); if (megame != 0) { if (mecolor == '?') sendcmd(nf, "accept %d", megame); else sendcmd(nf, "accept %d %c", megame, mecolor); (void) expectcmd(nf, 1, 105, 106, 0); } else { if (mecolor == '?') sendcmd(nf, "offer"); else sendcmd(nf, "offer %c", mecolor); (void) expectcmd(nf, 1, 103, 0); logmsg("waiting for opponent"); (void) expectcmd(nf, 1, 105, 106, 0); logmsg("opponent found"); } struct state s = s0; s.cureval = eval(&s); if (nttable > 0) s.curzhash = zhash(&s); while (1) { int ch = fgetc(nf); int r = ungetc(ch, nf); assert(r != EOF); if (isdigit(ch)) { s = readstate(nf, 1); s.cureval = eval(&s); if (nttable > 0) s.curzhash = zhash(&s); continue; } switch (ch) { case '?': { char *r = getnet(nf, "?"); char *q = strtok(r, " "); assert(!strcmp(q, "?")); char *tl = strtok(0, " "); char *tr = strtok(0, " "); assert(tl && tr); int t = readtimems(tl); t = 95 * t / (100 * ((81 - s.ply) / 2)); struct move m = idnegamax(&s, t, 0); logmsg("value %d at time %d depth %d for %s\n\n", v0, t, d0, movestr(&m)); move(&s, &m, 0); sendcmd(nf, "%s", movestr(&m)); printstate(&s, 1); if (ponder) (void) idnegamax(&s, 0, nf); continue; } case '!': assert(fgetc(nf) == '!'); int ch; do ch = fgetc(nf); while (isspace(ch)); ungetc(ch, nf); struct move m = getmove(nf, &s); move(&s, &m, 0); continue; case '=': (void) getnet(nf, "="); break; case 'X': (void) getnet(nf, "X"); break; default: (void) getnet(nf, "..."); continue; } break; } fclose(nf); }
int main(int argc, char *argv[], char *env[]) { struct sockaddr_storage from; int on = 1; socklen_t fromlen; register int ch; int i; #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) int tos = -1; #endif initsetproctitle(argc, argv, env); pfrontp = pbackp = ptyobuf; netip = netibuf; #ifdef USE_SSL /* we need to know the fullpath to the location of the * certificate that we will be running with as we cannot * be sure of the cwd when we are launched */ sprintf(cert_filepath,"%s/%s",X509_get_default_cert_dir(), "telnetd.pem"); ssl_cert_file=cert_filepath; ssl_key_file=NULL; #endif /* USE_SSL */ while ((ch = getopt(argc, argv, "d:a:e:lhnNr:I:D:B:sS:a:X:L:z:")) != EOF) { switch(ch) { #ifdef USE_SSL case 'z': { char *origopt; origopt=strdup(optarg); optarg=strtok(origopt,","); while(optarg!=NULL) { if (strcmp(optarg, "debug") == 0 ) { ssl_debug_flag=1; } else if (strcmp(optarg, "ssl") == 0 ) { ssl_only_flag=1; } else if (strcmp(optarg, "certsok") == 0 ) { ssl_certsok_flag=1; } else if ( (strcmp(optarg, "!ssl") == 0) || (strcmp(optarg, "nossl") == 0) ) { /* we may want to switch SSL negotiation off * for testing or other reasons */ ssl_disabled_flag=1; } else if (strcmp(optarg, "certrequired") == 0 ) { ssl_cert_required=1; } else if (strcmp(optarg, "secure") == 0 ) { ssl_secure_flag=1; } else if (strncmp(optarg, "verify=", strlen("verify=")) == 0 ) { ssl_verify_flag=atoi(optarg+strlen("verify=")); } else if (strncmp(optarg, "cert=", strlen("cert=")) == 0 ) { ssl_cert_file=optarg+strlen("cert="); } else if (strncmp(optarg, "key=", strlen("key=")) == 0 ) { ssl_key_file=optarg+strlen("key="); } else if (strncmp(optarg,"cipher=", strlen("cipher="))==0) { ssl_cipher_list=optarg+strlen("cipher="); } else { /* report when we are given rubbish so that * if the user makes a mistake they have to * correct it! */ fprintf(stderr,"Unknown SSL option %s\n",optarg); fflush(stderr); exit(1); } /* get the next one ... */ optarg=strtok(NULL,","); } /* if (origopt!=NULL) free(origopt); */ } break; #endif /* USE_SSL */ #ifdef AUTHENTICATE case 'a': /* * Check for required authentication level */ if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; } else if (strcasecmp(optarg, "none") == 0) { auth_level = 0; } else if (strcasecmp(optarg, "other") == 0) { auth_level = AUTH_OTHER; } else if (strcasecmp(optarg, "user") == 0) { auth_level = AUTH_USER; } else if (strcasecmp(optarg, "valid") == 0) { auth_level = AUTH_VALID; } else if (strcasecmp(optarg, "off") == 0) { /* * This hack turns off authentication */ auth_level = -1; } else { fprintf(stderr, "telnetd: unknown authorization level for -a\n"); } break; #endif /* AUTHENTICATE */ #ifdef BFTPDAEMON case 'B': bftpd++; break; #endif /* BFTPDAEMON */ case 'd': if (strcmp(optarg, "ebug") == 0) { debug++; break; } usage(); /* NOTREACHED */ break; #ifdef DIAGNOSTICS case 'D': /* * Check for desired diagnostics capabilities. */ if (!strcmp(optarg, "report")) { diagnostic |= TD_REPORT|TD_OPTIONS; } else if (!strcmp(optarg, "exercise")) { diagnostic |= TD_EXERCISE; } else if (!strcmp(optarg, "netdata")) { diagnostic |= TD_NETDATA; } else if (!strcmp(optarg, "ptydata")) { diagnostic |= TD_PTYDATA; } else if (!strcmp(optarg, "options")) { diagnostic |= TD_OPTIONS; } else { usage(); /* NOT REACHED */ } break; #endif /* DIAGNOSTICS */ #ifdef AUTHENTICATE case 'e': if (strcmp(optarg, "debug") == 0) { extern int auth_debug_mode; auth_debug_mode = 1; break; } usage(); /* NOTREACHED */ break; #endif /* AUTHENTICATE */ case 'h': hostinfo = 0; break; #ifdef LINEMODE case 'l': alwayslinemode = 1; break; #endif /* LINEMODE */ case 'L': loginprg = strdup(optarg); /* XXX what if strdup fails? */ break; case 'n': keepalive = 0; break; case 'N': numeric_hosts = 1; break; #ifdef SecurID case 's': /* SecurID required */ require_SecurID = 1; break; #endif /* SecurID */ case 'S': #ifdef HAS_GETTOS if ((tos = parsetos(optarg, "tcp")) < 0) fprintf(stderr, "%s%s%s\n", "telnetd: Bad TOS argument '", optarg, "'; will try to use default TOS"); #else fprintf(stderr, "%s%s\n", "TOS option unavailable; ", "-S flag not supported\n"); #endif break; #ifdef AUTHENTICATE case 'X': /* * Check for invalid authentication types */ auth_disable_name(optarg); break; #endif /* AUTHENTICATE */ default: fprintf(stderr, "telnetd: %c: unknown option\n", ch); /* FALLTHROUGH */ case '?': usage(); /* NOTREACHED */ } } #ifdef USE_SSL if (ssl_secure_flag || ssl_cert_required || ssl_certsok_flag) { /* in secure mode we *must* switch on the base level * verify checking otherwise we cannot abort connections * at the right place! */ if (ssl_verify_flag==0) ssl_verify_flag=1; } /* if we are not running in debug then any error * stuff from SSL debug *must* not go down * the socket (which 0,1,2 are all pointing to by * default) */ if (ssl_debug_flag) ssl_log_file="/telnetd.log"; if (!do_ssleay_init(1)) { if (bio_err!=NULL) { BIO_printf(bio_err,"do_ssleay_init() failed\n"); ERR_print_errors(bio_err); } else { fflush(stderr); fprintf(stderr,"do_ssleay_init() failed\n"); ERR_print_errors_fp(stderr); } exit(1); } if (ssl_debug_flag) { BIO_printf(bio_err,"secure %d certrequired %d verify %d\n", ssl_secure_flag,ssl_cert_required,ssl_verify_flag); for(i=0;i<argc;i++) BIO_printf(bio_err,"argv[%d]=\"%s\"\n",i,argv[i]); } #endif /* USE_SSL */ argc -= optind; argv += optind; if (debug) { if (argc > 1) { usage(); /* NOTREACHED */ } wait_for_connection((argc == 1) ? *argv : "telnet"); } openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); fromlen = sizeof (from); if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { fatalperror(2, "getpeername"); } if (keepalive && setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) { syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); } #if defined(HAS_IPPROTO_IP) && defined(IP_TOS) { # if defined(HAS_GETTOS) struct tosent *tp; if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) tos = tp->t_tos; # endif if (tos < 0) tos = 020; /* Low Delay bit */ if (tos && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) && (errno != ENOPROTOOPT) ) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); } #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */ #ifdef USE_SSL /* do the SSL stuff now ... before we play with pty's */ SSL_set_fd(ssl_con,0); if (ssl_only_flag) { /* hmm ... only when running talking to things like * https servers should we hit this code and then * we really don't care *who* we talk to :-) */ SSL_set_verify(ssl_con,ssl_verify_flag,NULL); if (SSL_accept(ssl_con) <= 0) { static char errbuf[1024]; sprintf(errbuf,"SSL_accept error %s\n", ERR_error_string(ERR_get_error(),NULL)); syslog(LOG_WARNING, "%s", errbuf); BIO_printf(bio_err,"%s",errbuf); /* go to sleep to make sure we are noticed */ sleep(10); SSL_free(ssl_con); _exit(1); } else { ssl_active_flag=1; } } #endif /* USE_SSL */ net = 0; netopen(); doit((struct sockaddr *)&from, fromlen); /* NOTREACHED */ return 0; } /* end of main */