[C] cgi

M.Ä.N.E

Stammgast
Ich habe mir nen Apache http Server eingerichtet um was mit cgi zu testen nun funtzt das nicht so wie ich das will der Code lautet:
Code:
/* location.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Listing fragt REMOTE_ADDR ab. Lässt sich der Wert nicht
 * auslesen, gibt das CGI-Programm den Statuscode 500 zurück.
 * Ansonsten werden die verbotenen IP-Adressen in forbidden mit
 * REMOTE_ADDR überprüft und entsprechende Maßnahmen getroffen */
/* Die Liste der IP-Adressen, welche keinen Zutritt auf der Seite
 * haben sollen */
char *forbidden[] = {
   "127.0.0.1", "168.123.6.1", NULL
};
/* Weiterleitung zu einer URL
 * url ist die URL, wohin Sie den User weiterleiten
 */
void print_location(char *url) {
   printf("Location: %s\n\n", url);
   /* Für den Fall, dass ein alter Browser keine
    * automatische Weiterleitung unterstützt */
   printf("Content-Type: text/html\n\n");
   printf("<html><head>\n");
   printf("<title>Weiterleitung zu %s</title>\n",url);
   printf("</head><body><pre>\n");
   printf("Weiter gehts <a href=\"%s\">hier</a>",url);
   printf("</pre></body></html>\n");
}
/* Statuscode zurückgeben */
void print_status(char *status) {
   printf("Status: %s", status);
}
int main(void) {
   char *p;
   int i;
   /* IP-Adresse ermitteln */
   p = getenv("REMOTE_ADDR");
   if( p == NULL) { /* Fehler bei getenv-Abfrage */
      print_status("500");
      return EXIT_FAILURE;
   }
   for(i=0; forbidden[i] != NULL; i++)
      if(strcmp(p, forbidden[i]) == 0) {
         /* Diese IP hat keinen Zutritt */
         print_status("403");
         return EXIT_FAILURE;
      }
   /* Ok, der User wird auf die Willkommen-Seite weitergeleitet.
    * Die URL auf Ihre Bedürfnisse anpassen */
   print_location("http://localhost/welcome.html");
   return EXIT_SUCCESS;
}

Leider komt immer der Fehler 500 wenn eigentlich 403(kein Zutritt) kommen sollte und im Error Log steh nur: Premature end of script headers: location.cgi
Und es leigt nicht daran das bei der Abfrage oben was nicht geht das hab ich getestet.

Wie muss ich den Code ändern das es funtzt? Ich glaub es hat was mit "return EXIT_FAILURE;" zu tun.
 

froeschli

Stammgast
Code:
int main(void) {
   char *p;
   int i;
   /* ip-adresse ermitteln */
   p = [COLOR="Red"]getenv("remote_addr")[/COLOR];
   if( [COLOR="Red"]p == null[/COLOR]) { /* fehler bei getenv-abfrage */
      print_status("500");
      return exit_failure;
   }
   for(i=0; forbidden[i] != null; i++)
      if(strcmp(p, forbidden[i]) == 0) {
         /* diese ip hat keinen zutritt */
         print_status("403");
         return exit_failure;
      }
   /* ok, der user wird auf die willkommen-seite weitergeleitet.
    * die url auf ihre bedürfnisse anpassen */
   print_location("http://localhost/welcome.html");
   return exit_success;
}

leider komt immer der fehler 500 wenn eigentlich 403(kein zutritt) kommen sollte und im error log steh nur: Premature end of script headers: Location.cgi
und es leigt nicht daran das bei der abfrage oben was nicht geht das hab ich getestet.

Wie muss ich den code ändern das es funtzt? Ich glaub es hat was mit "return exit_failure;" zu tun.

Du versuchst mittels der Funktion getenv die IP-Adresse des aufrufenden PCs zu ermitteln. Aus irgendeinem Grund scheitert dies jedoch. Das erkennst du daran, dass die Variable p den Wert null enthält. Anschliessend wird der Fehler 500 ausgegeben und mit return wird die Methode verlassen. Dein Code ist an und für sich schon korrekt, aber mit der Methode getenv("remote_addr") stimmt etwas nicht.

Gruss froeschli
 

M.Ä.N.E

Stammgast
Nein so weit ich das sehe ist mit der Funktion alles in Ordnung, ich vermute der Server könnte falsch konfiguriert sein. das der den Fehler 403 nicht kennt oder so was.
 

froeschli

Stammgast
Damit dein Code einen Fehler 500 ausgibt, muss die Variable p=NULL sein. Dies ist nur der Fall, wenn getenv("remote_addr") einen NULL-Wert zurück liefert...

Kannst du mittels
Code:
print_status("500");
[COLOR="Red"]printf("Wert: " %c, p)[/COLOR]
return exit_failure;
mal den Wert von der Variable p ausgeben, nachdem sie mit getenv() gefüllt wurde? Wenn dort nichts steht, dann liegt dein Problem definitiv bei der Methode getenv()...

Gruss froeschli
 

LMS

Stammgast
Hallo
Habs mal selbst ausprobiert, die gleiche Fehleranzeige bekommen und ich weiss glaub, woran es liegt. Schreib mal die Funktion print_status wie folgt um:
Code:
/* Statuscode zurückgeben */
void print_status(char *status) {
   printf("Status: %s[color=red]\n\n[/color]", status);
}
Also hinten noch 2 Newlines anhängen. Probier es jetzt mal aus und wenn es beim Firefox nicht funktioniert, nimm mal den IE. Bei mir kommt beim Firefox nur eine weisse Seite, beim IE wird aber richtigerweise der Fehlercode 403 angezeigt. Aber vielleicht funktioniert es bei dir bei problemlos. Auf jeden Fall gehören hinter die Header-Infos immer zwei neue Zeilen, sonst kanns der Browser nicht richtig interpretieren. Bei der Funktion print_location wird es bei "Location: ... " und bei "Content-Type ..." auch so gemacht.

Gruss
LMS
 

M.Ä.N.E

Stammgast
Also es kommt jetzt keine Fehler 500 Meldung mehr aber auch keine 403 ich werde in jedem Fall auf welcome.html umgeleitet habs auf IE, FireFox und Chrome getestet.
 

LMS

Stammgast
Also es kommt jetzt keine Fehler 500 Meldung mehr aber auch keine 403 ich werde in jedem Fall auf welcome.html umgeleitet habs auf IE, FireFox und Chrome getestet.

Und du hast deinen ursprünglichen Code verwendet, einfach mit den Anpassungen? Von wo aus greifst du auf den Server zu? Ist die betreffende IP im forbidden-Array aufgeführt?
 

M.Ä.N.E

Stammgast
Ja ich habe einfach die Anpassungen gemacht. und dann mit localhost/cgi-bin/location.cgi
aufgerufen also 127.0.0.1 . und die ist aufgeführt. Irgendwie wird das return EXIT_FAILURE ignoriert und das Programm fährt weiter zur Umleitung nach welcom.html
 

LMS

Stammgast
Glaube nicht, dass es an EXIT_FAILURE liegt, das ist ja nur der Return-Wert. Du könntest anstelle dessen auch irgend eine Zahl schreiben, also z.B. return 1 und es käme währscheinlich das gleiche heraus.

Nimm mal diesen Code und schaue was die ergänzte Funktion debug() für einen Output produziert bzw. was im Browser steht:
Code:
/* location.c */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Listing fragt REMOTE_ADDR ab. Lässt sich der Wert nicht
 * auslesen, gibt das CGI-Programm den Statuscode 500 zurück.
 * Ansonsten werden die verbotenen IP-Adressen in forbidden mit
 * REMOTE_ADDR überprüft und entsprechende Maßnahmen getroffen */
/* Die Liste der IP-Adressen, welche keinen Zutritt auf der Seite
 * haben sollen */
char *forbidden[] = {
   "127.0.0.1", "168.123.6.1", NULL
};
/* Weiterleitung zu einer URL
 * url ist die URL, wohin Sie den User weiterleiten
 */
void print_location(char *url) {
   printf("Location: %s\n\n", url);
   /* Für den Fall, dass ein alter Browser keine
    * automatische Weiterleitung unterstützt */
   printf("Content-Type: text/html\n\n");
   printf("<html><head>\n");
   printf("<title>Weiterleitung zu %s</title>\n",url);
   printf("</head><body><pre>\n");
   printf("Weiter gehts <a href=\"%s\">hier</a>",url);
   printf("</pre></body></html>\n");
}

void debug(char* ip, char* text) {
   printf("Content-Type: text/plain\n\n");
   printf("Meine IP =  %s\n", ip);
   printf("Status = %s", text);
}


/* Statuscode zurückgeben */
void print_status(char *status) {
   printf("Status: %s\n\n", status);
}
int main(void) {
   char *p;
   int i;
   /* IP-Adresse ermitteln */
   p = getenv("REMOTE_ADDR");
   if( p == NULL) { /* Fehler bei getenv-Abfrage */
      print_status("500");
      return EXIT_FAILURE;
   }
   for(i=0; forbidden[i] != NULL; i++)
      if(strcmp(p, forbidden[i]) == 0) {
         /* Diese IP hat keinen Zutritt */
         //print_status("403");
         debug(p, "if-clause erreicht und somit forbidden IP");
         return EXIT_FAILURE;
      }
   /* Ok, der User wird auf die Willkommen-Seite weitergeleitet.
    * Die URL auf Ihre Bedürfnisse anpassen */
   debug(p, "if-clause nicht erreicht und somit erlaubte IP");
   //print_location("http://localhost/welcome.html");
   return EXIT_SUCCESS;
}
 

M.Ä.N.E

Stammgast
Komisch er zeigt mir das an:

Meine IP = ::1 EDIT: ::1 Ist localhost für IPv6 hab das bei utorrent instaliert.
Status = if-clause nicht erreicht und somit erlaubte IP

Hat das was mit dem Loopback-Interface zu tun den auf den anderen PCs funktioniert es?
Denn wenn ich die Adresse mit localhost aufrufe kommt als IP ::1 raus wenn ich aber 127.0.0.1 zum aufrufen verwende also http://127.0.0.1/cgi-bin/location.cgi dann funtzt dann kommt zwar nur der weisse Bildschrim anstat der 403 Meldung aber das ist ja nicht schlim.
 
Zuletzt bearbeitet:

LMS

Stammgast
Komisch er zeigt mir das an:

Meine IP = ::1 EDIT: ::1 Ist localhost für IPv6 hab das bei utorrent instaliert.

Ja genau. Wahrscheinlich steht das in deiner Hosts-Datei so. (C:\WINDOWS\system32\drivers\etc\hosts). Lösung wird wohl sein, die Adresse ::1 in dem forbidden-Array ebenfalls einzutragen, je nachdem was du erreichen oder testen willst. Aber das ist dir wahrscheinlich ohnehin klar.

Noch einen Tipp zu dem Status 403. Du könntest natürlich auch die Funktion print_status() analog zu print_location() abändern, im Sinne von:

Code:
void print_status(char *status, char *fehlertext) {
   printf("Status: %s\n\n", status);
   /* Anzeige für Browser, die Status: nicht unterstützten */
   printf("Content-Type: text/html\n\n");
   printf("<html><head>\n");
   printf("<title>Fehlercode %s</title>\n",status);
   printf("</head><body><pre>\n");
   printf("Fehlercode %s. \n",status);
   printf("Grund: %s\n", fehlertext);
   printf("</pre></body></html>\n");
}

EDIT: oder wahrscheinlich besser so, weil der Header nicht 2x übertragen werden kann (Fallunterscheidung dürfte wahrscheinlich schwer werden. Von dem her wird wahrscheinlicht print_location auch nicht richtig funktionieren):

void print_status(char *status, char *fehlertext) {
   printf("Status: %s\n\n", status);
   /* Anzeige für Browser, die Status: nicht unterstützten */
   printf("Fehlercode %s\n",status);
   printf("Grund: %s\n", fehlertext);
}
Und beim Aufruf der Funktion den entsprechenden Fehlertext mitgeben, z.B.
Code:
print_status("403", "Sie haben keine Berechtigung zur Anzeige dieser Seite");
 
Zuletzt bearbeitet:

LMS

Stammgast
@froeschli:
Kein Problem. Das Thema hat mich grad interessiert und ich habe gesehen, dass die Lösung etwa in diese Richtung gehen könnte.
 
Oben