Főoldal | Adatszerkezetek | Könyvtárak | Fájllista | Adatmezők | Globális elemek

openrt.c

Ugrás a fájl dokumentációjához.
00001 
00011 #include <netdb.h>
00012 #include <stdio.h>
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <sys/socket.h>
00016 #include <unistd.h>
00017 #include <sys/types.h>
00018 #include <ctype.h>
00019 
00020 #include <regex.h>
00021 #include <locale.h>
00022 
00023 #include <errno.h>
00024 
00026 #define ERROR_NETWORK 3
00027 
00028 #define ERROR_PARAM 4
00029 
00030 #define ERROR_CODING 5
00031 
00032 #define RET_OPENRELAY 1
00033 #define RET_NOT_OPEN_RELAY 0
00034 
00035 struct param_t {
00036         int help; // "-h" paraméter
00037         int verbose; // "-v" paraméter - verbose uzemmod
00038         char *host;
00039         char *from;
00040         char *to;
00041         char *comment;
00042         int timeout;
00043         int port;
00044 };
00045 
00046 int mailaddr_test(char *);
00047 
00053 void get_params(int argc, char *argv[], struct param_t *p) {
00054         int c;
00055         opterr = 0;
00056 
00058         while ((c = getopt (argc, argv, "hvf:u:c:t:")) != -1) {
00059                 switch (c) {
00060                         case 'h':
00061                                 p->help = 1;
00062                                 break;
00063                         case 'v':
00064                                 p->verbose = 1;
00065                                 break;
00067                         case 'f':
00068                                 p->from = optarg;
00069                                 if (0 != mailaddr_test(p->from)) {
00070                                         fprintf(stderr, "Invalid sender address. (%s)\n", p->from);
00071                                         exit(ERROR_PARAM);
00072                                 }
00073                                 break;
00075                         case 'u':
00076                                 p->to = optarg;
00077                                 if (0 != mailaddr_test(p->to)) {
00078                                         fprintf(stderr, "Invalid recipient address.\n");
00079                                         exit(ERROR_PARAM);
00080                                 }
00081                                 break;
00083                         case 'c':
00084                                 p->comment = optarg;
00085                                 break;
00086                         // TODO - ez hasznalva van?
00087                         case 't':
00088                                 p->timeout = atoi(optarg);
00089                                 if (p->timeout < 0 || p->timeout > 60) {
00090                                         fprintf(stderr, "Invalid timeout: %s (interpreted as %d)\n",
00091                                                 optarg, p->timeout);
00092                                         exit(ERROR_PARAM);
00093                                 }
00094                                 break;
00096                         case '?':
00097                                 if (isprint (optopt)) {
00098                                         fprintf(stderr, "Unknown option `-%c'.\n", optopt);
00099                                 } else {
00100                                         fprintf(stderr, "Unknown option character `\\x%x'.\n",
00101                                                 optopt);
00102                                 }
00103                                 exit(ERROR_PARAM);
00104                                 break;
00105                         default:
00106                                 fprintf(stderr, "Unknown getopt() action.\n");
00107                                 exit(ERROR_CODING);
00108                 }
00109         }
00110         
00114         if (optind < argc) {
00115                 p->host = argv[optind];
00116         } else {
00117                 fprintf(stderr, "Empty hostname.\n");
00118                 exit(ERROR_PARAM);
00119         }
00120          
00121 
00126         optind++;
00127         if (optind < argc) {
00128                 int tp;
00129                 tp = atoi(argv[optind]);
00130                 if ((tp < 1) || (tp > 65535)) {
00131                         fprintf(stderr, "Invalid port number: %s (interpreted as %d)\n", 
00132                                 argv[optind], tp);
00133                         exit(ERROR_PARAM);
00134                 } else {
00135                         p->port = tp;
00136                 }
00137         }
00138 
00142         optind++;
00143         if (optind < argc) {
00144                 fprintf(stderr, "Unknown parameter: %s \n", argv[optind]);
00145                 exit(ERROR_PARAM); 
00146         }
00147 
00148         return;
00149 }
00150 
00153 void default_params(struct param_t *p) {
00154         memset(p, 0, sizeof(struct param_t));
00155         
00156         p->help = 0;
00157         p->verbose = 0;
00158         p->from = p->to = p->comment = NULL; 
00159         p->timeout = 60;
00160         p->port = 25; // default SMTP port
00161         return;
00162 }
00163 
00171 void print_message(char from, char* msg_text) {
00172     const char delimiters[] = "\n";
00173     char *token, *cp;
00174         int i = 0;
00175         
00176     cp = strdup(msg_text); // kell egy másolat az strtok miatt
00177         if (NULL == cp) {
00178                 fprintf(stderr, "There is not enough memory (strdup).");
00179                 exit(ERROR_CODING);
00180         }
00181 
00183         while (cp[i] != '\0') {
00184                 if ('\r' == cp[i]) {
00185                         cp[i] = ' ';
00186                 }
00187                 i++;
00188         }
00189 
00191         token = strtok(cp, delimiters);
00192         if (NULL == token) {
00193                 fprintf(stderr, "Invalid data? (print_message)\n");
00194         } else {
00195                 do  {
00196                         if ('S' == from) {
00197                                 printf("<<<");
00198                         } else {
00199                                 printf(">>>");
00200                         }
00201                         printf(" %s\n", token);
00202                 } while (NULL != (token = strtok(NULL, delimiters)));
00203         }
00204         free(cp);
00205 }
00206 
00207 
00214 int send_message(int sock, char *msg_text, int verbose) {
00215     
00216     if (1 == verbose) print_message('C', msg_text);
00217         
00218         if (send(sock, msg_text, strlen(msg_text), 0) < 0) {
00219                 perror("send");
00220                 return -1;
00221     }
00222     return 0;
00223 }
00224 
00230 int rt_quit(int sock, int ret, int verbose) {
00231 
00232         if (-1 != sock) {
00233                 send_message(sock, "\r\nQUIT\r\n", verbose);
00234                 close(sock);
00235         }
00236 
00237         if (1 == verbose) {
00238                 printf("return code: %d\n", ret);
00239                 switch (ret) {
00240                         case ERROR_NETWORK:
00241                                 printf("Network error.\n");
00242                                 break;
00243                         case ERROR_PARAM:
00244                                 printf("Error around the paramter(s).\n");
00245                                 break;
00246                         case ERROR_CODING:
00247                                 printf("Internal error.\n");
00248                                 break;
00249                         case RET_OPENRELAY:
00250                                 printf("The host is an open-relay server.\n");
00251                                 break;
00252                         case RET_NOT_OPEN_RELAY:
00253                                 printf("The host is NOT an open-relay server.\n");
00254                                 break;
00255                         default:
00256                                 printf("Unknown return value.\n");
00257                                 break;
00258                 }
00259         }
00260         
00261         exit(ret);      
00262 }
00263 
00274 int receive_message(int sock, int answer_ok, char *msg_text, int msg_len, int timeout, int verbose) {
00275         int rcvlen;
00276         char msg_num[8] = {0}; // ideiglenes hely az uzenet kodjanak
00277         int msg_code = 0;
00278         int i;
00279         
00280         struct timeval tv; //timeout
00281         fd_set read_fds; // fajlleiro halmaz
00282         int fdmax;
00283         int retval;
00284 
00285         FD_ZERO(&read_fds); 
00286         FD_SET(sock, &read_fds); 
00287         fdmax = sock;
00288 
00289         tv.tv_sec = timeout; 
00290         tv.tv_usec = 0;
00291 
00293         retval = select(fdmax + 1, &read_fds, NULL, NULL, &tv);
00294         if (-1 == retval) {
00295                 perror("select");
00296                 rt_quit(sock, ERROR_NETWORK, verbose);
00297         }
00298 
00299         if (FD_ISSET(sock, &read_fds)) {
00300                 rcvlen = recv(sock, msg_text, msg_len, 0); // uzenet vetele             
00301         } else {
00302                 rt_quit(sock, ERROR_NETWORK, verbose);
00303         }
00304         
00305         if (rcvlen < 0) {
00306                 perror("recv");
00307                 rt_quit(sock, ERROR_NETWORK, verbose);
00308         } else if (0 == rcvlen) {
00309                 fprintf(stderr, "Connection reset by peer.\n");
00310                 rt_quit(-1, ERROR_NETWORK, verbose);
00311         } else {
00312                 msg_text[rcvlen] = '\0';
00313                 if (1 == verbose) print_message('S', msg_text);
00314                 
00315                 if (NULL != (strchr(msg_text, ' '))) {
00318                     i = 0;
00319                     while ((msg_text[i] != ' ') && (msg_text[i] != '\0')) {
00320                                 i++;
00321                                 // ettol hosszab hibakod nem nagyon van
00322                                 if (i > 5) {
00323                                         fprintf(stderr, "Invalid answer from the SMTP server.\n");
00324                                         rt_quit(sock, ERROR_NETWORK, verbose);
00325                                 }
00326                     }
00327 
00328                         i = (i > sizeof(msg_num) - 1) ? sizeof(msg_num) - 1 : i;
00329                     strncpy(msg_num, msg_text, i);
00330                     //printf("num: %s\n", msg_num);
00331                     msg_code = atoi(msg_num);
00332                         
00334                         if (msg_code > 999 || msg_code < 100) {
00335                                 fprintf(stderr, "Invalid answer from the SMTP server.\n");
00336                                 rt_quit(sock, ERROR_NETWORK, verbose);
00337                         }
00338 
00341                         if (550 == msg_code || 554 == msg_code) {
00342                                 rt_quit(sock, RET_NOT_OPEN_RELAY, verbose);
00343                         }
00344 
00345                         if ((msg_code != answer_ok) && (0 != answer_ok)) {
00346                                 fprintf(stderr, "Invalid answer from the SMTP server.\n");
00347                                 if (1 != verbose) {
00348                                         print_message('S', msg_text);
00349                                 }
00350                                 rt_quit(sock, ERROR_NETWORK, verbose);
00351                         }
00352                         
00353                 } else {
00354                     fprintf(stderr, "Invalid answer from the SMTP server.\n");
00355                     rt_quit(sock, ERROR_NETWORK, verbose);
00356                 }
00357         }
00358         
00359         return msg_code;
00360 }
00361 
00364 void usage(void) {
00365         printf("Usage:\topenrt [-v] [-t timeout] -f sender_addr "); 
00366         printf("-u recipient_addr [-c comment] <hostname> <port>\n");
00367         printf("\topenrt -h\n");
00368         printf("Options:\n \
00369         -h\t\t\tthis help\n  \
00370         -f sender_addr\t\tsender-addr\n  \
00371         -u recipient_addr\tto-addr\n  \
00372         -v\t\t\tverbose mode\n  \
00373         -c comment\t\textra comments to the mail\n  \
00374         -t timeout\t\ttimeout in second(s)\n");
00375 }
00376 
00383 int test_smtp(int sock, struct param_t *params) {
00384         int ret = 0;
00385         char msg_text[512];
00386         char tmp_text[2048];
00387         char host[256];
00388         
00390         ret = receive_message(sock, 220, msg_text, sizeof(msg_text), params->timeout, params->verbose);
00391 
00393         if (-1 == gethostname(host, sizeof(host))) {
00394                 fprintf(stderr, "Couldn't get hostname (gethostname()).\n");
00395                 exit(ERROR_CODING);
00396         }
00397         
00402         ret = snprintf(tmp_text, sizeof(tmp_text), "HELO %s\r\n", host);
00403         if (ret < 0) {
00404                 fprintf(stderr, "Internal error (snprintf).");
00405                 exit(ERROR_CODING);
00406         }
00407         send_message(sock, tmp_text, params->verbose);
00408         
00410         receive_message(sock, 250, msg_text, sizeof(msg_text), params->timeout, params->verbose);
00411 
00413         ret = snprintf(tmp_text, sizeof(tmp_text), "MAIL FROM: %s\r\n", params->from);
00414         if (ret < 0) {
00415                 fprintf(stderr, "Internal error (snprintf).");
00416                 return ERROR_CODING;
00417         }
00418 
00419         send_message(sock, tmp_text, params->verbose);
00420         receive_message(sock, 250, msg_text, sizeof(msg_text), params->timeout, params->verbose);
00421 
00423         ret = snprintf(tmp_text, sizeof(tmp_text), "RCPT TO: %s\r\n", params->to);
00424         if (ret < 0) {
00425                 fprintf(stderr, "Internal error (snprintf).");
00426                 return ERROR_CODING;
00427         }
00428         
00429         send_message(sock, tmp_text, params->verbose);
00430         ret = receive_message(sock, 0, msg_text, sizeof(msg_text), params->timeout, params->verbose);
00431 
00432         
00433         send_message(sock, "DATA\r\n", params->verbose);
00434         receive_message(sock, 354, msg_text, sizeof(msg_text), params->timeout, params->verbose);
00435 
00437         ret = snprintf(tmp_text, sizeof(tmp_text), "To: %s\r\n" \
00438                         "From: %s\r\n" \
00439                         "Subject: open-relay test message\r\n" \
00440                         "\r\n" \
00441                         "This is a test message which check your SMTP server as an\r\n" \
00442                         "open-relay server and try to send a message with its.\r\n" \
00443                         "\r\n" \
00444                         "Please ignore this e-mail.\r\n" \
00445                         "\r\n" \
00446                         "%s\r\n" \
00447                         "\r\n" \
00448                         "EOF\r\n" \
00449                         ".\r\n", params->to, params->from, params->comment);
00450         if (ret < 0) {
00451                 fprintf(stderr, "Internal error (snprintf).");
00452                 return ERROR_CODING;
00453         }
00454                         
00455         send_message(sock, tmp_text, params->verbose);
00456         ret = receive_message(sock, 0, msg_text, sizeof(msg_text), params->timeout, params->verbose);
00457         
00458         if (250 == ret) {
00459                 ret = RET_OPENRELAY;
00460         } else {
00462                 ret = RET_NOT_OPEN_RELAY;
00463         }
00464 
00465         return ret;
00466 }
00467 
00473 int mailaddr_test(char *mailaddr) {
00474         int ret;
00475         regex_t  ford;
00476         
00477         ret = 0; // visszateresi ertek
00478 
00480         if (NULL == mailaddr) {
00481                 return 1;
00482         }
00483 
00485     if (regcomp(&ford, 
00486                 "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*$", 
00487                 REG_EXTENDED) != 0) {
00489                         fprintf(stderr, "Internal error in the regular expression.\n");
00490                         exit(ERROR_CODING);
00491         }
00492         
00493         if ((ret = regexec(&ford, mailaddr, 0, NULL, 0)) == 0) {
00494                 ret = 0; // OK az e-mail cim
00495         } else {
00496                 ret = 1; // nem illeszkedik, hibas
00497         }
00498 
00499         regfree(&ford);
00500         return ret;
00501 }
00502 
00505 int main(int argc, char *argv[]) {
00506         struct hostent *host;
00507         struct sockaddr_in addr;
00508         
00509         int ret; // visszateresi ertek
00510         int sock; // socket azonosito
00511 
00512         struct param_t params;
00513         
00515         if ((0 == geteuid()) || (0 == getegid())) {
00516                 fprintf(stderr, "Don't use this program as root.\n");
00517                 exit(ERROR_PARAM);
00518         }
00519 
00521         if (2 > argc) {
00522                 usage();
00523                 exit(0);
00524         }
00525         
00527         default_params(&params);
00528         get_params(argc, argv, &params);
00529         
00530         if (1 == params.help) {
00531                 usage();
00532                 exit(0);
00533         }
00534         
00535         if (NULL == params.host || NULL == (host = gethostbyname(params.host))) {
00536                 fprintf(stderr, "Invalid hostname.\n");
00537                 exit(ERROR_PARAM);
00538         }
00539         
00540         if (0 != params.verbose) {
00541                 printf("Connection to %s...\n", params.host);
00542         }
00543         
00544         if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00545                 perror("socket");
00546                 exit(ERROR_NETWORK);
00547         }
00548         
00549         memset(&addr, 0, sizeof(addr));
00550         addr.sin_family = AF_INET;
00551         addr.sin_port = htons(params.port);
00552         addr.sin_addr = *((struct in_addr *) (host->h_addr));
00553         
00554         if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
00555                 perror("connect");
00556                 exit(ERROR_NETWORK);
00557         }
00558 
00559         if (0 != params.verbose) {
00560                 printf("Connection established.\n");
00561         }
00562 
00564         ret = test_smtp(sock, &params);
00565 
00567         rt_quit(sock, ret, params.verbose);
00568 
00569         return 0; // ez itt mar nem is nagyon kellene
00570 }

Projekt: labhf Készült: Thu Apr 13 00:40:39 2006 Készítette:   doxygen 1.4.2