123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- program httpget;
- {$mode objfpc}
- {$h+}
- uses sysutils, ssockets, gnutls, uriparser;
- Const
- logLevel = 0; // Set to positive value to enable logging.
- // Correct this for your system.
- DefaultCerts : PChar = '/etc/ssl/certs/ca-certificates.crt';
- MAX_BUF = 1024*256;
- MSG = 'GET %s HTTP/1.0'#13#10'Host: %s'#13#10#13#10;
- Procedure MyLogFunc(level : longint; msg : PChar); cdecl;
- begin
- writeln(StdErr,'Log[',Level:2,']: ',msg);
- end;
- Var
- sock : TInetSocket;
- ret : integer;
- session : tgnutls_session_t;
- buf : Array[0..MAX_BUF] of char;
- cred : tgnutls_certificate_credentials_t;
- errptr,desc : pchar;
- FN, URL,S, HostName : String;
- port : word;
- uri : TURI;
- begin
- if paramCount<1 then
- begin
- writeln('Usage : ',ExtractFileName(ParamStr(0)),' url');
- Halt(1);
- end;
- url:=ParamStr(1);
- uri:=ParseURI(URL,'https',443);
- hostname:=uri.Host;
- if uri.Protocol<>'https' then
- begin
- Writeln('Only https supported');
- Halt(1);
- end;
- Port:=URI.Port;
- FN:=uri.Path+URI.Document;
- if (URI.Params<>'') then
- FN:=FN+'?'+URI.Params;
- if FN='' then FN:='/';
- LoadGNutls();
- gnutls_global_init();
- ret := gnutls_certificate_allocate_credentials (@cred);
- if (ret <> GNUTLS_E_SUCCESS) then
- begin
- writeln(stderr, 'error: gnutls_certificate_allocate_credentials: ', gnutls_strerror(ret));
- halt(1);
- end;
- ret := gnutls_certificate_set_x509_trust_file(cred, defaultcerts, GNUTLS_X509_FMT_PEM);
- if (ret = 0) then
- begin
- writeln(stderr, 'error: no certificates found in:', defaultcerts);
- halt(1);
- end
- else if (ret < 0) then
- begin
- writeln(stderr, 'error: gnutls_certificate_set_x509_trust_files(',defaultcerts,'): ',
- gnutls_strerror(ret));
- halt(1);
- end;
- if (logLevel>0) then
- begin
- gnutls_global_set_log_function(@MyLogFunc);
- gnutls_global_set_log_level(logLevel);
- end;
- gnutls_init(@session, GNUTLS_CLIENT);
- // We can also use
- // ret:=gnutls_set_default_priority(session);
- ret := gnutls_priority_set_direct(session, 'NORMAL', @errptr);
- if (ret <> GNUTLS_E_SUCCESS) then
- begin
- writeln(stderr, 'error: gnutls_priority_set_direct: ',gnutls_strerror(ret) , ' error: at: ', errptr);
- halt(1);
- end;
- ret := gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
- if (ret <> GNUTLS_E_SUCCESS) then
- begin
- writeln(stderr, 'error: gnutls_credentials_set: ', gnutls_strerror(ret));
- halt(1);
- end;
- Sock:=TINetSocket.Create(HostName,Port);
- gnutls_transport_set_int(session, Sock.Handle);
- gnutls_handshake_set_timeout(session,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
- ret := gnutls_server_name_set(session, GNUTLS_NAME_DNS,pchar(HostName), length(HostName));
- if (ret <> GNUTLS_E_SUCCESS) then
- begin
- writeln(stderr, 'error: gnutls_server_name_set: ', gnutls_strerror(ret));
- halt(1);
- end;
-
- gnutls_session_set_verify_cert(session,pchar(HostName),0);
-
- Repeat
- ret:=gnutls_handshake(session);
- if Ret<>GNUTLS_E_SUCCESS then
- Case ret of
- GNUTLS_E_AGAIN : Writeln(StdErr,'Handshake again');
- GNUTLS_E_INTERRUPTED : Writeln(StdErr,'Handshake interrupted');
- else
- Writeln(StdErr,'Error ',ret,' received, fatal : ',gnutls_error_is_fatal(ret));
- end;
- until (ret>=0) or (gnutls_error_is_fatal(ret) <> 0);
- if (ret < 0) then
- begin
- writeln(stderr, '*** Handshake failed');
- gnutls_perror(ret);
- end
- else
- begin
- desc := gnutls_session_get_desc(session);
- writeln(StdErr,'- Session info: ', desc);
- // gnutls_free(desc);
- end;
- S:=Format(Msg,[FN,HostName]);
- Writeln(StdErr,'Sending request : ',S);
- gnutls_record_send(session, Pchar(S), length(S));
- repeat
- ret := gnutls_record_recv(session, @buf, MAX_BUF);
- if (ret=0) then
- writeln(StdErr,'- Peer has closed the TLS connection\n')
- else if ((ret < 0) and (gnutls_error_is_fatal(ret) = 0)) then
- writeln(stderr, '*** Warning: ', gnutls_strerror(ret))
- else if (ret < 0) and (ret<>GNUTLS_E_PREMATURE_TERMINATION) then
- Writeln(stderr, '*** Error: ', ret, ' : ',gnutls_strerror(ret))
- else if (ret > 0) then
- begin
- writeln(StdErr,'- Received ',ret,' bytes: ');
- SetLength(S,Ret);
- Move(Buf[0],S[1],Ret);
- Write(S);
- end;
- until (ret<=0) and Not ((ret=GNUTLS_E_INTERRUPTED) or (Ret=GNUTLS_E_AGAIN));
- Writeln;
- gnutls_bye(session, GNUTLS_SHUT_RDWR);
- Sock.Free;
- gnutls_deinit(session);
- gnutls_certificate_free_credentials(cred);
- gnutls_global_deinit();
- FreeGnuTLS;
- end.
|