2016-12-30 4 views
0

Ich versuche ein C-Programm, um OAuth 2 Authcode von Google Server (in Form einer HTTP-GET-Anfrage) zu akzeptieren. Wenn ich versuche, recv() zu lesen, wird der Fehler ausgegeben. Der Transportendpunkt ist nicht verbunden. Dies ist nur, nachdem ich eine nicht negative ganze Zahl nach dem Aufruf von accept() erhalten habe. Ich habe das gleiche mit Java und Netcat-Dienstprogramm versucht, beide funktionieren gut für mich.Socket geschlossen vor recv ohne Aufruf zu schließen

Hier ist der Code.

#include<stdio.h> 
#include<string.h> 
#include<arpa/inet.h> 
#include<unistd.h> 
#include<stdlib.h> 
#include<pthread.h> 
#include<sys/select.h> 
#include<fcntl.h> 
#include<errno.h> 

void *send_authcode_request(void *sockaddr_ptr); 

int main() { 
    char *bind_addr = "127.0.0.1"; 
    char *errmsg = (char *) malloc(1024); 
    short int port = 0; 

    setvbuf(stdout, NULL, _IONBF, 0); 

    struct sockaddr_in local_addr; 
    struct sockaddr_in client_addr; 
    local_addr.sin_family = AF_INET; 
    local_addr.sin_port = port; 
    inet_aton(bind_addr, &(local_addr.sin_addr)); 
    memset(&(local_addr.sin_zero), '\0', 8); 

    int sock_id = socket(AF_INET, SOCK_STREAM, 0); 
    /*fcntl(sock_id, F_SETFL, O_NONBLOCK);*/ 

    if (bind(sock_id, (struct sockaddr*) &local_addr, sizeof(struct sockaddr)) == -1) { 
     sprintf(errmsg, "Cannot bind socket to the port #%d", port); 
     perror(errmsg); 
     return -1; 
    } 
    if (listen(sock_id, 20) == -1) { 
     sprintf(errmsg, "Cannot listen to connections on the socket"); 
     perror(errmsg); 
     return -1; 
    } 
    int sin_size = sizeof(struct sockaddr_in); 
    if(getsockname(sock_id, (struct sockaddr *) &local_addr, &sin_size) == -1) { 
     sprintf(errmsg, "Unable to get the current address of the socket"); 
     perror(errmsg); 
     return -1; 
    } 
    printf("\n Port no after binding #%d\n", ntohs(local_addr.sin_port)); 

    pthread_t authcode_req_thread; 
    pthread_create(&authcode_req_thread, NULL, send_authcode_request, (void *) &local_addr); 

    fd_set read_fs; 
    FD_ZERO(&read_fs); 
    FD_SET(sock_id, &read_fs); 

    long accept_timeout = 60*10; 

    struct timeval tv; 
    tv.tv_sec = accept_timeout; 
    tv.tv_usec = 0; 

    char auth_code_info[1024]; 

    if (select(sock_id+1, &read_fs, NULL, NULL, &tv) > 0) { 
     /*if(accept4(sock_id, (struct sockaddr *) &client_addr, &sin_size, SOCK_NONBLOCK) == -1) {*/ 
     if(accept(sock_id, (struct sockaddr *) &client_addr, &sin_size) >= 0) { 
      /* Accept auth code */ 
      int bytesread; 
      if ((bytesread = recv(sock_id, auth_code_info, 1023, 0)) == -1) { 
       perror(errmsg); 
       return -1; 
      } 
      printf("\n%s\n", auth_code_info); 
      char *reply = "Done! You can now close the window"; 
      send(sock_id, reply, strlen(reply), 0); 
     } else { 
      sprintf(errmsg, "No client connected within timeout of %ld seconds", accept_timeout); 
      perror(errmsg); 
      return -1; 
     } 
    } else { 
     sprintf(errmsg, "No client connected within timeout of %ld seconds", accept_timeout); 
     perror(errmsg); 
     return -1; 
    } 
    close(sock_id); 
    printf("\n"); 
    return 0; 
} 

void *send_authcode_request(void *ptr) { 
    char *scope = "https://www.googleapis.com/auth/drive"; 
    char *client_id = "1098482466406-c3h15ld90l03s0pl4rm7qq54fcb49t78.apps.googleusercontent.com"; 
    const char *temp_authcode_uri = "xdg-open \"https://accounts.google.com/o/oauth2/v2/auth?scope=%s&redirect_uri=http://127.0.0.1:%d&response_type=code&client_id=%s\""; 

    struct sockaddr_in *socket_address = (struct sockaddr_in *) ptr; 

    int max_authcode_uri_len = strlen(temp_authcode_uri) + strlen(client_id) + strlen(scope); 
    char *authcode_uri = (char *) malloc(max_authcode_uri_len); 
    sprintf(authcode_uri, temp_authcode_uri, scope, ntohs(socket_address->sin_port), client_id); 
    printf("\n%s\n", authcode_uri); 
    system(authcode_uri); 
} 

Allerdings, wenn ich auf den gleichen Port netcat, hören zeigt es die HTTP-Anforderung vom Browser. Also habe ich den TCP-Verkehr für den Port mit Wireshark verfolgt und einen anderen Verkehr gefunden als den, den ich bei Verwendung von netcat erhalte.

Für mein Programm

No.  Time   Source    Destination   Protocol Length Info 
     1 0.000000000 127.0.0.1    127.0.0.1    TCP  74  48234 → 49927 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7268636 TSecr=0 WS=128 
     2 0.000010715 127.0.0.1    127.0.0.1    TCP  74  49927 → 48234 [SYN, ACK] Seq=0 Ack=1 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7268636 TSecr=7268636 WS=128 
     3 0.000020978 127.0.0.1    127.0.0.1    TCP  66  48234 → 49927 [ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7268636 TSecr=7268636 
     4 0.000059901 127.0.0.1    127.0.0.1    TCP  74  48236 → 49927 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7268636 TSecr=0 WS=128 
     5 0.000064624 127.0.0.1    127.0.0.1    TCP  74  49927 → 48236 [SYN, ACK] Seq=0 Ack=1 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7268636 TSecr=7268636 WS=128 
     6 0.000070536 127.0.0.1    127.0.0.1    TCP  66  48236 → 49927 [ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7268636 TSecr=7268636 
     7 0.000384302 127.0.0.1    127.0.0.1    TCP  66  49927 → 48234 [FIN, ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7268636 TSecr=7268636 
     8 0.000412860 127.0.0.1    127.0.0.1    TCP  66  49927 → 48236 [RST, ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7268636 TSecr=7268636 
     9 0.000997709 127.0.0.1    127.0.0.1    TCP  66  48234 → 49927 [FIN, ACK] Seq=1 Ack=2 Win=43776 Len=0 TSval=7268637 TSecr=7268636 
    10 0.000974316 127.0.0.1    127.0.0.1    TCP  66  [TCP Keep-Alive] 48234 → 49927 [ACK] Seq=1 Ack=2 Win=43776 Len=0 TSval=7268637 TSecr=7268636 
    11 0.001005630 127.0.0.1    127.0.0.1    TCP  66  49927 → 48234 [ACK] Seq=2 Ack=2 Win=43776 Len=0 TSval=7268637 TSecr=7268637 
    12 0.001047174 127.0.0.1    127.0.0.1    TCP  74  48238 → 49927 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7268637 TSecr=0 WS=128 
    13 0.001051855 127.0.0.1    127.0.0.1    TCP  54  49927 → 48238 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0 
    14 0.237652758 127.0.0.1    127.0.0.1    TCP  74  48240 → 49927 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7268696 TSecr=0 WS=128 
    15 0.237664760 127.0.0.1    127.0.0.1    TCP  54  49927 → 48240 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0 
    16 5.243733213 127.0.0.1    127.0.0.1    TCP  74  48242 → 49927 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7269947 TSecr=0 WS=128 
    17 5.243751969 127.0.0.1    127.0.0.1    TCP  54  49927 → 48242 [RST, ACK] Seq=1 Ack=1 Win=0 Len=0 

wenn netcat

Mit netcat verwenden, erhalte ich die benötigte HTTP-Get-Anfrage die Authentifizierungs-Token enthält.

No.  Time   Source    Destination   Protocol Length Info 
     1 0.000000000 127.0.0.1    127.0.0.1    TCP  74  45064 → 2807 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7233868 TSecr=0 WS=128 
     2 0.000008155 127.0.0.1    127.0.0.1    TCP  74  2807 → 45064 [SYN, ACK] Seq=0 Ack=1 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7233868 TSecr=7233868 WS=128 
     3 0.000015895 127.0.0.1    127.0.0.1    TCP  66  45064 → 2807 [ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7233868 TSecr=7233868 
     4 0.000043941 127.0.0.1    127.0.0.1    TCP  74  45066 → 2807 [SYN] Seq=0 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7233868 TSecr=0 WS=128 
     5 0.000047566 127.0.0.1    127.0.0.1    TCP  74  2807 → 45066 [SYN, ACK] Seq=0 Ack=1 Win=43690 Len=0 MSS=65495 SACK_PERM=1 TSval=7233868 TSecr=7233868 WS=128 
     6 0.000050911 127.0.0.1    127.0.0.1    TCP  66  45066 → 2807 [ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7233868 TSecr=7233868 
     7 0.000074583 127.0.0.1    127.0.0.1    TCP  66  2807 → 45066 [RST, ACK] Seq=1 Ack=1 Win=43776 Len=0 TSval=7233868 TSecr=7233868 
     8 0.000833585 127.0.0.1    127.0.0.1    HTTP  654 GET /?code=4/zuPKCQlOvIcJq5gAvPRGLQdkiICNzOmAQUAx9apK5go HTTP/1.1 
     9 0.000841060 127.0.0.1    127.0.0.1    TCP  66  2807 → 45064 [ACK] Seq=1 Ack=589 Win=44928 Len=0 TSval=7233868 TSecr=7233868 
    10 45.005118503 127.0.0.1    127.0.0.1    TCP  66  [TCP Keep-Alive] 45064 → 2807 [ACK] Seq=588 Ack=1 Win=43776 Len=0 TSval=7245120 TSecr=7233868 
    11 45.005166221 127.0.0.1    127.0.0.1    TCP  66  [TCP Keep-Alive ACK] 2807 → 45064 [ACK] Seq=1 Ack=589 Win=44928 Len=0 TSval=7245120 TSecr=7233868 

Wie Sie sehen können, sendet mein Programm einen FIN-Flag, die in netcat nicht da ist. Wo gehe ich hier falsch?

+1

Veröffentlichen Sie keine Bilder von Text! – Olaf

+0

@Olaf Ich würde nicht ein Wireshark Screenshot ein Bild des Textes genau nennen. Sie können nicht einfach die Paketliste kopieren/einfügen, nicht leicht. – dbush

+0

@dbush: Sie können es in eine Textdatei ablegen (nicht sicher, ob es überhaupt möglich ist, in die Zwischenablage zu schreiben). – Olaf

Antwort

0

Sie lesen von der falschen Buchse.

Die Buchse, die Sie an listen übergeben, ist nur eine abhörende Buchse. Es stellt keinen verbundenen Socket dar. Es wird nur durch eine lokale IP und einen Port identifiziert.

Wenn Sie accept aufrufen, gibt diese Funktion den Dateideskriptor des verbundenen Sockets zurück. Diese Sockets werden durch eine lokale IP und einen Port sowie eine entfernte IP und einen entfernten Port identifiziert. Diese Funktion kann daher mehrfach für mehrere eingehende Verbindungen mit jeweils eigenem Socket aufgerufen werden. Auf diese Weise können Sie mit Verbindungen von mehreren Endpunkten umgehen.

speichern den Rückgabewert von accept als neuen Sockel, und verwenden, die ein bis send und recv auf. Achten Sie darauf, close es, wenn Sie fertig sind.

Verwandte Themen