httpget.pp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. program httpget;
  2. {$mode objfpc}
  3. {$h+}
  4. uses sysutils, ssockets, gnutls, uriparser;
  5. Const
  6. logLevel = 0; // Set to positive value to enable logging.
  7. // Correct this for your system.
  8. DefaultCerts : PChar = '/etc/ssl/certs/ca-certificates.crt';
  9. MAX_BUF = 1024*256;
  10. MSG = 'GET %s HTTP/1.0'#13#10'Host: %s'#13#10#13#10;
  11. Procedure MyLogFunc(level : longint; msg : PChar); cdecl;
  12. begin
  13. writeln(StdErr,'Log[',Level:2,']: ',msg);
  14. end;
  15. Var
  16. sock : TInetSocket;
  17. ret : integer;
  18. session : tgnutls_session_t;
  19. buf : Array[0..MAX_BUF] of char;
  20. cred : tgnutls_certificate_credentials_t;
  21. errptr,desc : pchar;
  22. FN, URL,S, HostName : String;
  23. port : word;
  24. uri : TURI;
  25. begin
  26. if paramCount<1 then
  27. begin
  28. writeln('Usage : ',ExtractFileName(ParamStr(0)),' url');
  29. Halt(1);
  30. end;
  31. url:=ParamStr(1);
  32. uri:=ParseURI(URL,'https',443);
  33. hostname:=uri.Host;
  34. if uri.Protocol<>'https' then
  35. begin
  36. Writeln('Only https supported');
  37. Halt(1);
  38. end;
  39. Port:=URI.Port;
  40. FN:=uri.Path+URI.Document;
  41. if (URI.Params<>'') then
  42. FN:=FN+'?'+URI.Params;
  43. if FN='' then FN:='/';
  44. LoadGNutls();
  45. gnutls_global_init();
  46. ret := gnutls_certificate_allocate_credentials (@cred);
  47. if (ret <> GNUTLS_E_SUCCESS) then
  48. begin
  49. writeln(stderr, 'error: gnutls_certificate_allocate_credentials: ', gnutls_strerror(ret));
  50. halt(1);
  51. end;
  52. ret := gnutls_certificate_set_x509_trust_file(cred, defaultcerts, GNUTLS_X509_FMT_PEM);
  53. if (ret = 0) then
  54. begin
  55. writeln(stderr, 'error: no certificates found in:', defaultcerts);
  56. halt(1);
  57. end
  58. else if (ret < 0) then
  59. begin
  60. writeln(stderr, 'error: gnutls_certificate_set_x509_trust_files(',defaultcerts,'): ',
  61. gnutls_strerror(ret));
  62. halt(1);
  63. end;
  64. if (logLevel>0) then
  65. begin
  66. gnutls_global_set_log_function(@MyLogFunc);
  67. gnutls_global_set_log_level(logLevel);
  68. end;
  69. gnutls_init(@session, GNUTLS_CLIENT);
  70. // We can also use
  71. // ret:=gnutls_set_default_priority(session);
  72. ret := gnutls_priority_set_direct(session, 'NORMAL', @errptr);
  73. if (ret <> GNUTLS_E_SUCCESS) then
  74. begin
  75. writeln(stderr, 'error: gnutls_priority_set_direct: ',gnutls_strerror(ret) , ' error: at: ', errptr);
  76. halt(1);
  77. end;
  78. ret := gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
  79. if (ret <> GNUTLS_E_SUCCESS) then
  80. begin
  81. writeln(stderr, 'error: gnutls_credentials_set: ', gnutls_strerror(ret));
  82. halt(1);
  83. end;
  84. Sock:=TINetSocket.Create(HostName,Port);
  85. gnutls_transport_set_int(session, Sock.Handle);
  86. gnutls_handshake_set_timeout(session,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
  87. ret := gnutls_server_name_set(session, GNUTLS_NAME_DNS,pchar(HostName), length(HostName));
  88. if (ret <> GNUTLS_E_SUCCESS) then
  89. begin
  90. writeln(stderr, 'error: gnutls_server_name_set: ', gnutls_strerror(ret));
  91. halt(1);
  92. end;
  93. gnutls_session_set_verify_cert(session,pchar(HostName),0);
  94. Repeat
  95. ret:=gnutls_handshake(session);
  96. if Ret<>GNUTLS_E_SUCCESS then
  97. Case ret of
  98. GNUTLS_E_AGAIN : Writeln(StdErr,'Handshake again');
  99. GNUTLS_E_INTERRUPTED : Writeln(StdErr,'Handshake interrupted');
  100. else
  101. Writeln(StdErr,'Error ',ret,' received, fatal : ',gnutls_error_is_fatal(ret));
  102. end;
  103. until (ret>=0) or (gnutls_error_is_fatal(ret) <> 0);
  104. if (ret < 0) then
  105. begin
  106. writeln(stderr, '*** Handshake failed');
  107. gnutls_perror(ret);
  108. end
  109. else
  110. begin
  111. desc := gnutls_session_get_desc(session);
  112. writeln(StdErr,'- Session info: ', desc);
  113. // gnutls_free(desc);
  114. end;
  115. S:=Format(Msg,[FN,HostName]);
  116. Writeln(StdErr,'Sending request : ',S);
  117. gnutls_record_send(session, Pchar(S), length(S));
  118. repeat
  119. ret := gnutls_record_recv(session, @buf, MAX_BUF);
  120. if (ret=0) then
  121. writeln(StdErr,'- Peer has closed the TLS connection\n')
  122. else if ((ret < 0) and (gnutls_error_is_fatal(ret) = 0)) then
  123. writeln(stderr, '*** Warning: ', gnutls_strerror(ret))
  124. else if (ret < 0) and (ret<>GNUTLS_E_PREMATURE_TERMINATION) then
  125. Writeln(stderr, '*** Error: ', ret, ' : ',gnutls_strerror(ret))
  126. else if (ret > 0) then
  127. begin
  128. writeln(StdErr,'- Received ',ret,' bytes: ');
  129. SetLength(S,Ret);
  130. Move(Buf[0],S[1],Ret);
  131. Write(S);
  132. end;
  133. until (ret<=0) and Not ((ret=GNUTLS_E_INTERRUPTED) or (Ret=GNUTLS_E_AGAIN));
  134. Writeln;
  135. gnutls_bye(session, GNUTLS_SHUT_RDWR);
  136. Sock.Free;
  137. gnutls_deinit(session);
  138. gnutls_certificate_free_credentials(cred);
  139. gnutls_global_deinit();
  140. FreeGnuTLS;
  141. end.