httpget.pp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 : PAnsiChar = '/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 : PAnsiChar); 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 AnsiChar;
  20. cred : tgnutls_certificate_credentials_t;
  21. errptr,desc : PAnsiChar;
  22. FN, URL,S, HostName : String;
  23. port : word;
  24. A : AnsiString;
  25. uri : TURI;
  26. begin
  27. if paramCount<1 then
  28. begin
  29. writeln('Usage : ',ExtractFileName(ParamStr(0)),' url');
  30. Halt(1);
  31. end;
  32. url:=ParamStr(1);
  33. uri:=ParseURI(URL,'https',443);
  34. hostname:=uri.Host;
  35. if uri.Protocol<>'https' then
  36. begin
  37. Writeln('Only https supported');
  38. Halt(1);
  39. end;
  40. Port:=URI.Port;
  41. FN:=uri.Path+URI.Document;
  42. if (URI.Params<>'') then
  43. FN:=FN+'?'+URI.Params;
  44. if FN='' then FN:='/';
  45. LoadGNutls();
  46. gnutls_global_init();
  47. ret := gnutls_certificate_allocate_credentials (@cred);
  48. if (ret <> GNUTLS_E_SUCCESS) then
  49. begin
  50. writeln(stderr, 'error: gnutls_certificate_allocate_credentials: ', gnutls_strerror(ret));
  51. halt(1);
  52. end;
  53. ret := gnutls_certificate_set_x509_trust_file(cred, defaultcerts, GNUTLS_X509_FMT_PEM);
  54. if (ret = 0) then
  55. begin
  56. writeln(stderr, 'error: no certificates found in:', defaultcerts);
  57. halt(1);
  58. end
  59. else if (ret < 0) then
  60. begin
  61. writeln(stderr, 'error: gnutls_certificate_set_x509_trust_files(',defaultcerts,'): ',
  62. gnutls_strerror(ret));
  63. halt(1);
  64. end;
  65. if (logLevel>0) then
  66. begin
  67. gnutls_global_set_log_function(@MyLogFunc);
  68. gnutls_global_set_log_level(logLevel);
  69. end;
  70. gnutls_init(@session, GNUTLS_CLIENT);
  71. // We can also use
  72. // ret:=gnutls_set_default_priority(session);
  73. ret := gnutls_priority_set_direct(session, 'NORMAL', @errptr);
  74. if (ret <> GNUTLS_E_SUCCESS) then
  75. begin
  76. writeln(stderr, 'error: gnutls_priority_set_direct: ',gnutls_strerror(ret) , ' error: at: ', errptr);
  77. halt(1);
  78. end;
  79. ret := gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred);
  80. if (ret <> GNUTLS_E_SUCCESS) then
  81. begin
  82. writeln(stderr, 'error: gnutls_credentials_set: ', gnutls_strerror(ret));
  83. halt(1);
  84. end;
  85. Sock:=TINetSocket.Create(HostName,Port);
  86. gnutls_transport_set_int(session, Sock.Handle);
  87. gnutls_handshake_set_timeout(session,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
  88. A:=HostName;
  89. ret := gnutls_server_name_set(session, GNUTLS_NAME_DNS,PAnsiChar(A), length(A));
  90. if (ret <> GNUTLS_E_SUCCESS) then
  91. begin
  92. writeln(stderr, 'error: gnutls_server_name_set: ', gnutls_strerror(ret));
  93. halt(1);
  94. end;
  95. gnutls_session_set_verify_cert(session,PAnsiChar(A),0);
  96. Repeat
  97. ret:=gnutls_handshake(session);
  98. if Ret<>GNUTLS_E_SUCCESS then
  99. Case ret of
  100. GNUTLS_E_AGAIN : Writeln(StdErr,'Handshake again');
  101. GNUTLS_E_INTERRUPTED : Writeln(StdErr,'Handshake interrupted');
  102. else
  103. Writeln(StdErr,'Error ',ret,' received, fatal : ',gnutls_error_is_fatal(ret));
  104. end;
  105. until (ret>=0) or (gnutls_error_is_fatal(ret) <> 0);
  106. if (ret < 0) then
  107. begin
  108. writeln(stderr, '*** Handshake failed');
  109. gnutls_perror(ret);
  110. end
  111. else
  112. begin
  113. desc := gnutls_session_get_desc(session);
  114. writeln(StdErr,'- Session info: ', desc);
  115. // gnutls_free(desc);
  116. end;
  117. S:=Format(Msg,[FN,HostName]);
  118. Writeln(StdErr,'Sending request : ',S);
  119. A:=S;
  120. gnutls_record_send(session, PAnsiChar(A), length(A));
  121. repeat
  122. ret := gnutls_record_recv(session, @buf, MAX_BUF);
  123. if (ret=0) then
  124. writeln(StdErr,'- Peer has closed the TLS connection\n')
  125. else if ((ret < 0) and (gnutls_error_is_fatal(ret) = 0)) then
  126. writeln(stderr, '*** Warning: ', gnutls_strerror(ret))
  127. else if (ret < 0) and (ret<>GNUTLS_E_PREMATURE_TERMINATION) then
  128. Writeln(stderr, '*** Error: ', ret, ' : ',gnutls_strerror(ret))
  129. else if (ret > 0) then
  130. begin
  131. writeln(StdErr,'- Received ',ret,' bytes: ');
  132. SetLength(S,Ret);
  133. Move(Buf[0],S[1],Ret);
  134. Write(S);
  135. end;
  136. until (ret<=0) and Not ((ret=GNUTLS_E_INTERRUPTED) or (Ret=GNUTLS_E_AGAIN));
  137. Writeln;
  138. gnutls_bye(session, GNUTLS_SHUT_RDWR);
  139. Sock.Free;
  140. gnutls_deinit(session);
  141. gnutls_certificate_free_credentials(cred);
  142. gnutls_global_deinit();
  143. FreeGnuTLS;
  144. end.