This adds a patch which makes amtterm work against a machine running
Intel ME version 12.

This should really be upstream code, but it looks like upstream is inactive.
And without this patch amtterm is entirely useless against current machines.
So I think in this case it is worth patching it ourselves. I hope that if
upstream becomes active again a future update will make these patches
unnecessary.

ok?

diff 333077bd2bf861f2cff72b5e1058978bec71e982 /usr/ports
blob - 3e7ac289fa3294a3e6319c96ac84d0e7d9f6a73f
file + comms/amtterm/Makefile
--- comms/amtterm/Makefile
+++ comms/amtterm/Makefile
@@ -4,6 +4,7 @@ COMMENT-term=   cli client for Intel AMT serial-over-lan
 COMMENT-main=  client and tools for Intel AMT serial-over-lan
 
 V=             1.6
+REVISION=      0
 DISTNAME=      amtterm-$V
 PKGNAME-main=  amtterm-$V
 PKGNAME-term=  amtterm-cli-$V
@@ -16,10 +17,10 @@ HOMEPAGE=   https://www.kraxel.org/blog/linux/amtterm/
 # GPLv2+
 PERMIT_PACKAGE=        Yes
 
-WANTLIB-term += c
-WANTLIB += atk-1.0 c cairo cairo-gobject gdk-3 gdk_pixbuf-2.0
+WANTLIB-term += c crypto ssl
+WANTLIB += atk-1.0 c cairo cairo-gobject crypto gdk-3 gdk_pixbuf-2.0
 WANTLIB += gio-2.0 glib-2.0 gobject-2.0 gtk-3 harfbuzz intl pango-1.0
-WANTLIB += pangocairo-1.0 vte-2.91
+WANTLIB += pangocairo-1.0 ssl vte-2.91
 
 MASTER_SITES=  https://www.kraxel.org/releases/amtterm/
 
blob - /dev/null
file + comms/amtterm/patches/patch-GNUmakefile
--- /dev/null
+++ comms/amtterm/patches/patch-GNUmakefile
@@ -0,0 +1,42 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: GNUmakefile
+--- GNUmakefile.orig
++++ GNUmakefile
+@@ -1,11 +1,24 @@
+ # config
++USE_OPENSSL=1
++#USE_GNUTLS=1
+ srcdir        = .
+ VPATH = $(srcdir)
+ -include Make.config
+ include $(srcdir)/mk/Variables.mk
+ 
++ifdef USE_OPENSSL
++SSL_DEFS=-DUSE_OPENSSL
++pkglst+=openssl
++endif
++
++ifdef USE_GNUTLS
++SSL_DEFS=-DUSE_GNUTLS
++pkglst+=gnutls
++endif
++
+ CFLAGS        += -Wall -Wno-pointer-sign
+ CFLAGS        += -DVERSION='"$(VERSION)"'
++CFLAGS  += $(SSL_DEFS)
+ 
+ TARGETS       := amtterm
+ DESKTOP := $(wildcard *.desktop)
+@@ -60,8 +73,8 @@ distclean: clean
+ 
+ #################################################################
+ 
+-amtterm: amtterm.o redir.o tcp.o
+-gamt: gamt.o redir.o tcp.o parseconfig.o
++amtterm: amtterm.o redir.o tcp.o auth.o ssl.o
++gamt: gamt.o redir.o tcp.o parseconfig.o auth.o ssl.o
+ 
+ #################################################################
+ 
blob - /dev/null
file + comms/amtterm/patches/patch-amtterm_c
--- /dev/null
+++ comms/amtterm/patches/patch-amtterm_c
@@ -0,0 +1,49 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: amtterm.c
+--- amtterm.c.orig
++++ amtterm.c
+@@ -179,10 +179,18 @@ static void usage(FILE *fp)
+             "   -h            print this text\n"
+             "   -v            verbose (default)\n"
+             "   -q            quiet\n"
++            "   -L            use legacy authentication\n"
++#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
++            "   -C cacert     enable SSL and use PEM cacert file\n"
++#endif
+             "   -u user       username (default: admin)\n"
+             "   -p pass       password (default: $AMT_PASSWORD)\n"
+             "\n"
++#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
++            "By default port 16994 (SSL: 16995) is used.\n"
++#else
+             "By default port 16994 is used.\n"
++#endif
+           "If no password is given " APPNAME " will ask for one.\n"
+             "\n"
+             "-- \n"
+@@ -209,7 +217,7 @@ int main(int argc, char *argv[])
+       snprintf(r.pass, sizeof(r.pass), "%s", h);
+ 
+     for (;;) {
+-        if (-1 == (c = getopt(argc, argv, "hvqu:p:")))
++        if (-1 == (c = getopt(argc, argv, "hvqu:p:LC:")))
+             break;
+         switch (c) {
+       case 'v':
+@@ -225,6 +233,14 @@ int main(int argc, char *argv[])
+           snprintf(r.pass, sizeof(r.pass), "%s", optarg);
+           memset(optarg,'*',strlen(optarg)); /* rm passwd from ps list */
+           break;
++      case 'L':
++          r.legacy = 1;
++          break;
++#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
++      case 'C':
++          r.cacert = optarg;
++          break;
++#endif
+ 
+         case 'h':
+             usage(stdout);
blob - /dev/null
file + comms/amtterm/patches/patch-auth_c
--- /dev/null
+++ comms/amtterm/patches/patch-auth_c
@@ -0,0 +1,833 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: auth.c
+--- auth.c.orig
++++ auth.c
+@@ -0,0 +1,826 @@
++/*
++ *  Authentication helper functions.
++ *
++ *  Copyright (C) 2014 Andreas Steinmetz <a...@domdv.de>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License along
++ *  with this program; if not, write to the Free Software Foundation, Inc.,
++ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <string.h>
++#include <stdint.h>
++#include "auth.h"
++
++#define MD5_SIZE      16
++#define MD5_HEX               (MD5_SIZE<<1)
++#define MD5(a)                uint8_t a[MD5_SIZE]
++
++#define AUTH_SESS     0x13
++#define AUTH_SESS_REPLY       0x14
++
++#define AUTH_SUCCESS  0x00
++#define AUTH_FAIL     0x01
++
++#define TYPE_METHODS  0x00
++#define TYPE_PLAIN    0x01
++#define TYPE_RFC2069  0x03
++#define TYPE_RFC2617  0x04
++
++#define MAX_USER      32
++#define MAX_PASS      32
++#define MAX_REALM     64
++#define MAX_NONCE     MD5_HEX
++#define MAX_CNONCE    MD5_HEX
++#define MAX_RESPONSE  MD5_HEX
++#define MAX_QOP               8
++
++#define URI           "/RedirectionService"
++#define NC            "00000002"
++#define QOP           "auth"
++#define METHOD                "POST"
++
++#define put_header(data,length,type)                  \
++do {                                                  \
++      *data++=AUTH_SESS;                              \
++      *data++=AUTH_SUCCESS;                           \
++      *data++=0;                                      \
++      *data++=0;                                      \
++      *data++=type;                                   \
++      *data++=(unsigned char)(length);                \
++      *data++=(unsigned char)(length>>8);             \
++      *data++=(unsigned char)(length>>16);            \
++      *data++=(unsigned char)(length>>24);            \
++} while(0)
++
++#define put_element(data,element)                     \
++do {                                                  \
++      int length=strlen(element);                     \
++      *data++=(unsigned char)length;                  \
++      memcpy(data,element,length);                    \
++      data+=length;                                   \
++} while(0)
++
++#define get_header(data,len,method,status)            \
++do {                                                  \
++      if(data[0]!=AUTH_SESS_REPLY)goto out;           \
++      status=data[1];                                 \
++      if(data[4]!=method)goto out;                    \
++      len=data[8];                                    \
++      len<<=8;                                        \
++      len|=data[7];                                   \
++      len<<=8;                                        \
++      len|=data[6];                                   \
++      len<<=8;                                        \
++      len|=data[5];                                   \
++} while(0)
++
++#define get_element(data,len,element,max)             \
++do {                                                  \
++      int blen=*data++;                               \
++      if(blen>--len||blen>max)goto out;               \
++      memcpy(element,data,blen);                      \
++      element[blen]=0;                                \
++      data+=blen;                                     \
++      len-=blen;                                      \
++} while(0)
++
++typedef struct
++{
++      uint32_t md5[4];
++      uint32_t total;
++      uint8_t bfr[64];
++      uint8_t size;
++} md5_ctx;
++
++static void md5block(uint32_t *md5,uint8_t *block)
++{
++      register uint32_t a;
++      register uint32_t b;
++      register uint32_t c;
++      register uint32_t d;
++      uint32_t bfr[16];
++
++      a=block[3];
++      a<<=8;
++      a+=block[2];
++      a<<=8;
++      a+=block[1];
++      a<<=8;
++      bfr[0]=a+block[0];
++
++      a=block[7];
++      a<<=8;
++      a+=block[6];
++      a<<=8;
++      a+=block[5];
++      a<<=8;
++      bfr[1]=a+block[4];
++
++      a=block[11];
++      a<<=8;
++      a+=block[10];
++      a<<=8;
++      a+=block[9];
++      a<<=8;
++      bfr[2]=a+block[8];
++
++      a=block[15];
++      a<<=8;
++      a+=block[14];
++      a<<=8;
++      a+=block[13];
++      a<<=8;
++      bfr[3]=a+block[12];
++
++      a=block[19];
++      a<<=8;
++      a+=block[18];
++      a<<=8;
++      a+=block[17];
++      a<<=8;
++      bfr[4]=a+block[16];
++
++      a=block[23];
++      a<<=8;
++      a+=block[22];
++      a<<=8;
++      a+=block[21];
++      a<<=8;
++      bfr[5]=a+block[20];
++
++      a=block[27];
++      a<<=8;
++      a+=block[26];
++      a<<=8;
++      a+=block[25];
++      a<<=8;
++      bfr[6]=a+block[24];
++
++      a=block[31];
++      a<<=8;
++      a+=block[30];
++      a<<=8;
++      a+=block[29];
++      a<<=8;
++      bfr[7]=a+block[28];
++
++      a=block[35];
++      a<<=8;
++      a+=block[34];
++      a<<=8;
++      a+=block[33];
++      a<<=8;
++      bfr[8]=a+block[32];
++
++      a=block[39];
++      a<<=8;
++      a+=block[38];
++      a<<=8;
++      a+=block[37];
++      a<<=8;
++      bfr[9]=a+block[36];
++
++      a=block[43];
++      a<<=8;
++      a+=block[42];
++      a<<=8;
++      a+=block[41];
++      a<<=8;
++      bfr[10]=a+block[40];
++
++      a=block[47];
++      a<<=8;
++      a+=block[46];
++      a<<=8;
++      a+=block[45];
++      a<<=8;
++      bfr[11]=a+block[44];
++
++      a=block[51];
++      a<<=8;
++      a+=block[50];
++      a<<=8;
++      a+=block[49];
++      a<<=8;
++      bfr[12]=a+block[48];
++
++      a=block[55];
++      a<<=8;
++      a+=block[54];
++      a<<=8;
++      a+=block[53];
++      a<<=8;
++      bfr[13]=a+block[52];
++
++      a=block[59];
++      a<<=8;
++      a+=block[58];
++      a<<=8;
++      a+=block[57];
++      a<<=8;
++      bfr[14]=a+block[56];
++
++      a=block[63];
++      a<<=8;
++      a+=block[62];
++      a<<=8;
++      a+=block[61];
++      a<<=8;
++      bfr[15]=a+block[60];
++
++      a=md5[0];
++      b=md5[1];
++      c=md5[2];
++      d=md5[3];
++
++      a+=bfr[0];
++      a+=0xd76aa478;
++      a+=d^(b&(c^d));
++      a=(a<<7)|(a>>25);
++      a+=b;
++      d+=bfr[1];
++      d+=0xe8c7b756;
++      d+=c^(a&(b^c));
++      d=(d<<12)|(d>>20);
++      d+=a;
++      c+=bfr[2];
++      c+=0x242070db;
++      c+=b^(d&(a^b));
++      c=(c<<17)|(c>>15);
++      c+=d;
++      b+=bfr[3];
++      b+=0xc1bdceee;
++      b+=a^(c&(d^a));
++      b=(b<<22)|(b>>10);
++      b+=c;
++      a+=bfr[4];
++      a+=0xf57c0faf;
++      a+=d^(b&(c^d));
++      a=(a<<7)|(a>>25);
++      a+=b;
++      d+=bfr[5];
++      d+=0x4787c62a;
++      d+=c^(a&(b^c));
++      d=(d<<12)|(d>>20);
++      d+=a;
++      c+=bfr[6];
++      c+=0xa8304613;
++      c+=b^(d&(a^b));
++      c=(c<<17)|(c>>15);
++      c+=d;
++      b+=bfr[7];
++      b+=0xfd469501;
++      b+=a^(c&(d^a));
++      b=(b<<22)|(b>>10);
++      b+=c;
++      a+=bfr[8];
++      a+=0x698098d8;
++      a+=d^(b&(c^d));
++      a=(a<<7)|(a>>25);
++      a+=b;
++      d+=bfr[9];
++      d+=0x8b44f7af;
++      d+=c^(a&(b^c));
++      d=(d<<12)|(d>>20);
++      d+=a;
++      c+=bfr[10];
++      c+=0xffff5bb1;
++      c+=b^(d&(a^b));
++      c=(c<<17)|(c>>15);
++      c+=d;
++      b+=bfr[11];
++      b+=0x895cd7be;
++      b+=a^(c&(d^a));
++      b=(b<<22)|(b>>10);
++      b+=c;
++      a+=bfr[12];
++      a+=0x6b901122;
++      a+=d^(b&(c^d));
++      a=(a<<7)|(a>>25);
++      a+=b;
++      d+=bfr[13];
++      d+=0xfd987193;
++      d+=c^(a&(b^c));
++      d=(d<<12)|(d>>20);
++      d+=a;
++      c+=bfr[14];
++      c+=0xa679438e;
++      c+=b^(d&(a^b));
++      c=(c<<17)|(c>>15);
++      c+=d;
++      b+=bfr[15];
++      b+=0x49b40821;
++      b+=a^(c&(d^a));
++      b=(b<<22)|(b>>10);
++      b+=c;
++
++      a+=bfr[1];
++      a+=0xf61e2562;
++      a+=c^(d&(b^c));
++      a=(a<<5)|(a>>27);
++      a+=b;
++      d+=bfr[6];
++      d+=0xc040b340;
++      d+=b^(c&(a^b));
++      d=(d<<9)|(d>>23);
++      d+=a;
++      c+=bfr[11];
++      c+=0x265e5a51;
++      c+=a^(b&(d^a));
++      c=(c<<14)|(c>>18);
++      c+=d;
++      b+=bfr[0];
++      b+=0xe9b6c7aa;
++      b+=d^(a&(c^d));
++      b=(b<<20)|(b>>12);
++      b+=c;
++      a+=bfr[5];
++      a+=0xd62f105d;
++      a+=c^(d&(b^c));
++      a=(a<<5)|(a>>27);
++      a+=b;
++      d+=bfr[10];
++      d+=0x02441453;
++      d+=b^(c&(a^b));
++      d=(d<<9)|(d>>23);
++      d+=a;
++      c+=bfr[15];
++      c+=0xd8a1e681;
++      c+=a^(b&(d^a));
++      c=(c<<14)|(c>>18);
++      c+=d;
++      b+=bfr[4];
++      b+=0xe7d3fbc8;
++      b+=d^(a&(c^d));
++      b=(b<<20)|(b>>12);
++      b+=c;
++      a+=bfr[9];
++      a+=0x21e1cde6;
++      a+=c^(d&(b^c));
++      a=(a<<5)|(a>>27);
++      a+=b;
++      d+=bfr[14];
++      d+=0xc33707d6;
++      d+=b^(c&(a^b));
++      d=(d<<9)|(d>>23);
++      d+=a;
++      c+=bfr[3];
++      c+=0xf4d50d87;
++      c+=a^(b&(d^a));
++      c=(c<<14)|(c>>18);
++      c+=d;
++      b+=bfr[8];
++      b+=0x455a14ed;
++      b+=d^(a&(c^d));
++      b=(b<<20)|(b>>12);
++      b+=c;
++      a+=bfr[13];
++      a+=0xa9e3e905;
++      a+=c^(d&(b^c));
++      a=(a<<5)|(a>>27);
++      a+=b;
++      d+=bfr[2];
++      d+=0xfcefa3f8;
++      d+=b^(c&(a^b));
++      d=(d<<9)|(d>>23);
++      d+=a;
++      c+=bfr[7];
++      c+=0x676f02d9;
++      c+=a^(b&(d^a));
++      c=(c<<14)|(c>>18);
++      c+=d;
++      b+=bfr[12];
++      b+=0x8d2a4c8a;
++      b+=d^(a&(c^d));
++      b=(b<<20)|(b>>12);
++      b+=c;
++
++      a+=bfr[5];
++      a+=0xfffa3942;
++      a+=b^c^d;
++      a=(a<<4)|(a>>28);
++      a+=b;
++      d+=bfr[8];
++      d+=0x8771f681;
++      d+=a^b^c;
++      d=(d<<11)|(d>>21);
++      d+=a;
++      c+=bfr[11];
++      c+=0x6d9d6122;
++      c+=d^a^b;
++      c=(c<<16)|(c>>16);
++      c+=d;
++      b+=bfr[14];
++      b+=0xfde5380c;
++      b+=c^d^a;
++      b=(b<<23)|(b>>9);
++      b+=c;
++      a+=bfr[1];
++      a+=0xa4beea44;
++      a+=b^c^d;
++      a=(a<<4)|(a>>28);
++      a+=b;
++      d+=bfr[4];
++      d+=0x4bdecfa9;
++      d+=a^b^c;
++      d=(d<<11)|(d>>21);
++      d+=a;
++      c+=bfr[7];
++      c+=0xf6bb4b60;
++      c+=d^a^b;
++      c=(c<<16)|(c>>16);
++      c+=d;
++      b+=bfr[10];
++      b+=0xbebfbc70;
++      b+=c^d^a;
++      b=(b<<23)|(b>>9);
++      b+=c;
++      a+=bfr[13];
++      a+=0x289b7ec6;
++      a+=b^c^d;
++      a=(a<<4)|(a>>28);
++      a+=b;
++      d+=bfr[0];
++      d+=0xeaa127fa;
++      d+=a^b^c;
++      d=(d<<11)|(d>>21);
++      d+=a;
++      c+=bfr[3];
++      c+=0xd4ef3085;
++      c+=d^a^b;
++      c=(c<<16)|(c>>16);
++      c+=d;
++      b+=bfr[6];
++      b+=0x04881d05;
++      b+=c^d^a;
++      b=(b<<23)|(b>>9);
++      b+=c;
++      a+=bfr[9];
++      a+=0xd9d4d039;
++      a+=b^c^d;
++      a=(a<<4)|(a>>28);
++      a+=b;
++      d+=bfr[12];
++      d+=0xe6db99e5;
++      d+=a^b^c;
++      d=(d<<11)|(d>>21);
++      d+=a;
++      c+=bfr[15];
++      c+=0x1fa27cf8;
++      c+=d^a^b;
++      c=(c<<16)|(c>>16);
++      c+=d;
++      b+=bfr[2];
++      b+=0xc4ac5665;
++      b+=c^d^a;
++      b=(b<<23)|(b>>9);
++      b+=c;
++
++      a+=bfr[0];
++      a+=0xf4292244;
++      a+=c^(b|~d);
++      a=(a<<6)|(a>>26);
++      a+=b;
++      d+=bfr[7];
++      d+=0x432aff97;
++      d+=b^(a|~c);
++      d=(d<<10)|(d>>22);
++      d+=a;
++      c+=bfr[14];
++      c+=0xab9423a7;
++      c+=a^(d|~b);
++      c=(c<<15)|(c>>17);
++      c+=d;
++      b+=bfr[5];
++      b+=0xfc93a039;
++      b+=d^(c|~a);
++      b=(b<<21)|(b>>11);
++      b+=c;
++      a+=bfr[12];
++      a+=0x655b59c3;
++      a+=c^(b|~d);
++      a=(a<<6)|(a>>26);
++      a+=b;
++      d+=bfr[3];
++      d+=0x8f0ccc92;
++      d+=b^(a|~c);
++      d=(d<<10)|(d>>22);
++      d+=a;
++      c+=bfr[10];
++      c+=0xffeff47d;
++      c+=a^(d|~b);
++      c=(c<<15)|(c>>17);
++      c+=d;
++      b+=bfr[1];
++      b+=0x85845dd1;
++      b+=d^(c|~a);
++      b=(b<<21)|(b>>11);
++      b+=c;
++      a+=bfr[8];
++      a+=0x6fa87e4f;
++      a+=c^(b|~d);
++      a=(a<<6)|(a>>26);
++      a+=b;
++      d+=bfr[15];
++      d+=0xfe2ce6e0;
++      d+=b^(a|~c);
++      d=(d<<10)|(d>>22);
++      d+=a;
++      c+=bfr[6];
++      c+=0xa3014314;
++      c+=a^(d|~b);
++      c=(c<<15)|(c>>17);
++      c+=d;
++      b+=bfr[13];
++      b+=0x4e0811a1;
++      b+=d^(c|~a);
++      b=(b<<21)|(b>>11);
++      b+=c;
++      a+=bfr[4];
++      a+=0xf7537e82;
++      a+=c^(b|~d);
++      a=(a<<6)|(a>>26);
++      a+=b;
++      d+=bfr[11];
++      d+=0xbd3af235;
++      d+=b^(a|~c);
++      d=(d<<10)|(d>>22);
++      d+=a;
++      c+=bfr[2];
++      c+=0x2ad7d2bb;
++      c+=a^(d|~b);
++      c=(c<<15)|(c>>17);
++      c+=d;
++      b+=bfr[9];
++      b+=0xeb86d391;
++      b+=d^(c|~a);
++      b=(b<<21)|(b>>11);
++      b+=c;
++
++      md5[0]+=a;
++      md5[1]+=b;
++      md5[2]+=c;
++      md5[3]+=d;
++}
++
++static void md5init(register md5_ctx *ptr)
++{
++      ptr->total=ptr->size=0;
++      ptr->md5[0]=0x67452301;
++      ptr->md5[1]=0xefcdab89;
++      ptr->md5[2]=0x98badcfe;
++      ptr->md5[3]=0x10325476;
++}
++
++static void md5next(register uint8_t *data,register uint32_t length,
++      register md5_ctx *ptr)
++{
++      register uint32_t i;
++
++      ptr->total+=length;
++
++      for(i=ptr->size;(i&63)&&length;length--)ptr->bfr[i++]=*data++;
++
++      if(i==64)
++      {
++              i=0;
++              md5block(ptr->md5,ptr->bfr);
++      }
++
++      for(;length>63;data+=64,length-=64)
++              md5block(ptr->md5,data);
++
++      for(;length;length--)ptr->bfr[i++]=*data++;
++
++      ptr->size=(uint8_t)(i);
++}
++
++static void md5end(register uint8_t *result,register md5_ctx *ptr)
++{
++      register uint32_t i=ptr->size;
++
++      ptr->bfr[i++]=0x80;
++      if(i>56)
++      {
++              for(;i<64;i++)ptr->bfr[i]=0;
++              i=0;
++              md5block(ptr->md5,ptr->bfr);
++      }
++      for(;i<56;i++)ptr->bfr[i]=0;
++
++      ptr->bfr[56]=(uint8_t)((ptr->total)<<3);
++      ptr->bfr[57]=(uint8_t)((ptr->total)>>5);
++      ptr->bfr[58]=(uint8_t)((ptr->total)>>13);
++      ptr->bfr[59]=(uint8_t)((ptr->total)>>21);
++      ptr->bfr[60]=(uint8_t)((ptr->total)>>29);
++      ptr->bfr[61]=0;
++      ptr->bfr[62]=0;
++      ptr->bfr[63]=0;
++
++      md5block(ptr->md5,ptr->bfr);
++
++      result[ 0]=(uint8_t) (ptr->md5[0]);
++      result[ 1]=(uint8_t)((ptr->md5[0])>>8);
++      result[ 2]=(uint8_t)((ptr->md5[0])>>16);
++      result[ 3]=(uint8_t)((ptr->md5[0])>>24);
++      result[ 4]=(uint8_t) (ptr->md5[1]);
++      result[ 5]=(uint8_t)((ptr->md5[1])>>8);
++      result[ 6]=(uint8_t)((ptr->md5[1])>>16);
++      result[ 7]=(uint8_t)((ptr->md5[1])>>24);
++      result[ 8]=(uint8_t) (ptr->md5[2]);
++      result[ 9]=(uint8_t)((ptr->md5[2])>>8);
++      result[10]=(uint8_t)((ptr->md5[2])>>16);
++      result[11]=(uint8_t)((ptr->md5[2])>>24);
++      result[12]=(uint8_t) (ptr->md5[3]);
++      result[13]=(uint8_t)((ptr->md5[3])>>8);
++      result[14]=(uint8_t)((ptr->md5[3])>>16);
++      result[15]=(uint8_t)((ptr->md5[3])>>24);
++}
++
++static void bin2hex(unsigned char *bin,int len,char *hex)
++{
++      while(len--)
++      {
++              *hex=*bin>>4;
++              if(*hex>9)*hex+++='a'-10;
++              else *hex+++='0';
++              *hex=*bin++&0xf;
++              if(*hex>9)*hex+++='a'-10;
++              else *hex+++='0';
++      }
++      *hex=0;
++}
++
++int authenticate(int mode,char *user,char *pass,
++      int (*io)(void *parm,unsigned char *data,int len,int mode),void *parm)
++{
++      int r=-1;
++      int len;
++      int status;
++      int method;
++      unsigned char *ptr;
++      unsigned char bfr[512];
++      char realm[MAX_REALM+1];
++      char nonce[MAX_NONCE+1];
++      char cnonce[MAX_CNONCE+1];
++      char response[MAX_RESPONSE+1];
++      char qop[MAX_QOP+1];
++      char tmp[MD5_HEX+1];
++      MD5(md5);
++      md5_ctx ctx;
++
++      if(strlen(user)>MAX_USER||strlen(pass)>MAX_PASS)return -1;
++
++      ptr=bfr;
++      put_header(ptr,0,TYPE_METHODS);
++      if(io(parm,bfr,9,WRITE))goto out;
++
++      if(io(parm,bfr,9,READ))goto out;
++      get_header(bfr,len,TYPE_METHODS,status);
++      if(status!=AUTH_SUCCESS)goto out;
++      if(len>sizeof(bfr))goto out;
++      if(io(parm,bfr,len,READ))goto out;
++
++      for(method=0,ptr=bfr;len;len--)
++      {
++              if(!*ptr||*ptr>=sizeof(method)*8)return -1;
++              method|=1<<*ptr++;
++      }
++
++      if(method&(1<<TYPE_RFC2617))method=TYPE_RFC2617;
++      else if(method&(1<<TYPE_RFC2069))method=TYPE_RFC2069;
++      else if(method&(1<<TYPE_PLAIN))method=TYPE_PLAIN;
++      else goto out;
++
++      switch(method)
++      {
++      case TYPE_PLAIN:
++              len=strlen(user)+strlen(pass)+2;
++              ptr=bfr;
++              put_header(ptr,len,method);
++              put_element(ptr,user);
++              put_element(ptr,pass);
++              break;
++
++      case TYPE_RFC2069:
++      case TYPE_RFC2617:
++              len=strlen(user)+strlen(URI)+(method==TYPE_RFC2617?8:7);
++              ptr=bfr;
++              put_header(ptr,len,method);
++              put_element(ptr,user);
++              *ptr++=0;
++              *ptr++=0;
++              put_element(ptr,URI);
++              *ptr++=0;
++              *ptr++=0;
++              *ptr++=0;
++              *ptr=0;
++              if(io(parm,bfr,len+9,WRITE))goto out;
++
++              if(io(parm,bfr,9,READ))goto out;
++              get_header(bfr,len,method,status);
++              if(status!=AUTH_FAIL)goto out;
++              if(len>sizeof(bfr))goto out;
++              if(io(parm,bfr,len,READ))goto out;
++              ptr=bfr;
++              if(!len)goto out;
++              get_element(ptr,len,realm,MAX_REALM);
++              if(!len)goto out;
++              get_element(ptr,len,nonce,MAX_NONCE);
++              if(!len)*qop=0;
++              else get_element(ptr,len,qop,MAX_QOP);
++
++              if(method==TYPE_RFC2617)
++              {
++                      if(strcmp(qop,QOP))goto out;
++              }
++              else if(*qop)goto out;
++
++              if(io(parm,bfr,16,RANDOM))goto out;
++              md5init(&ctx);
++              md5next(bfr,16,&ctx);
++              md5end(md5,&ctx);
++              bin2hex(md5,MD5_SIZE,cnonce);
++
++              md5init(&ctx);
++              md5next((uint8_t *)user,strlen(user),&ctx);
++              md5next((uint8_t *)":",1,&ctx);
++              md5next((uint8_t *)realm,strlen(realm),&ctx);
++              md5next((uint8_t *)":",1,&ctx);
++              md5next((uint8_t *)pass,strlen(pass),&ctx);
++              md5end(md5,&ctx);
++              bin2hex(md5,MD5_SIZE,tmp);
++
++              md5init(&ctx);
++              md5next((uint8_t *)METHOD,strlen(METHOD),&ctx);
++              md5next((uint8_t *)":",1,&ctx);
++              md5next((uint8_t *)URI,strlen(URI),&ctx);
++              md5end(md5,&ctx);
++              bin2hex(md5,MD5_SIZE,response);
++
++              md5init(&ctx);
++              md5next((uint8_t *)tmp,strlen(tmp),&ctx);
++              md5next((uint8_t *)":",1,&ctx);
++              md5next((uint8_t *)nonce,strlen(nonce),&ctx);
++              md5next((uint8_t *)":",1,&ctx);
++              if(method==TYPE_RFC2617)
++              {
++                      md5next((uint8_t *)NC,strlen(NC),&ctx);
++                      md5next((uint8_t *)":",1,&ctx);
++                      md5next((uint8_t *)cnonce,strlen(cnonce),&ctx);
++                      md5next((uint8_t *)":",1,&ctx);
++                      md5next((uint8_t *)qop,strlen(qop),&ctx);
++                      md5next((uint8_t *)":",1,&ctx);
++              }
++              md5next((uint8_t *)response,strlen(response),&ctx);
++              md5end(md5,&ctx);
++              bin2hex(md5,MD5_SIZE,response);
++
++              len=strlen(user)+strlen(realm)+strlen(nonce)
++                      +strlen(URI)+strlen(cnonce)+strlen(NC)
++                      +strlen(response)+strlen(qop)+
++                      (method==TYPE_RFC2617?8:7);
++              ptr=bfr;
++              put_header(ptr,len,method);
++              put_element(ptr,user);
++              put_element(ptr,realm);
++              put_element(ptr,nonce);
++              put_element(ptr,URI);
++              put_element(ptr,cnonce);
++              put_element(ptr,NC);
++              put_element(ptr,response);
++              put_element(ptr,qop);
++              break;
++
++      default:goto out;
++      }
++
++      if(io(parm,bfr,len+9,WRITE))goto out;
++
++      if(mode)
++      {
++              if(io(parm,bfr,9,READ))goto out;
++              get_header(bfr,len,method,status);
++              if(len>sizeof(bfr))goto out;
++              if(io(parm,bfr,len,READ))goto out;
++
++              if(status==AUTH_SUCCESS)r=0;
++              else r=-2;
++      }
++      else r=0;
++
++out:  memset(bfr,0,sizeof(bfr));
++
++      return r;
++}
blob - /dev/null
file + comms/amtterm/patches/patch-auth_h
--- /dev/null
+++ comms/amtterm/patches/patch-auth_h
@@ -0,0 +1,13 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: auth.h
+--- auth.h.orig
++++ auth.h
+@@ -0,0 +1,6 @@
++#define READ  0
++#define WRITE 1
++#define RANDOM        2
++
++extern int authenticate(int mode,char *user,char *pass,
++      int (*io)(void *parm,unsigned char *data,int len,int mode),void *parm);
blob - /dev/null
file + comms/amtterm/patches/patch-gamt_c
--- /dev/null
+++ comms/amtterm/patches/patch-gamt_c
@@ -0,0 +1,65 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: gamt.c
+--- gamt.c.orig
++++ gamt.c
+@@ -84,6 +84,8 @@ static char amt_user[32] = "admin";
+ static char amt_pass[32];
+ static int amt_trace;
+ static int amt_debug;
++static int amt_legacy;
++static char *amt_cacert;
+ 
+ static int gamt_getstring(GtkWidget *window, char *title, char *message,
+                         char *dest, int dlen, int hide);
+@@ -768,6 +770,8 @@ static int gamt_connect(struct gamt_window *gamt)
+     gamt->redir.cb_data  = gamt;
+     gamt->redir.cb_recv  = recv_gtk;
+     gamt->redir.cb_state = state_gtk;
++    gamt->redir.legacy   = amt_legacy;
++    gamt->redir.cacert   = amt_cacert;
+ 
+     if (-1 == redir_connect(&gamt->redir))
+       return -1;
+@@ -905,8 +909,16 @@ static void usage(FILE *fp)
+             "   -c color      text color\n"
+             "   -b color      background color\n"
+             "   -l file       logfile\n"
++            "   -L            use legacy authentication\n"
++#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
++            "   -C cacert     enable SSL and use PEM cacert file\n"
++#endif
+             "\n"
++#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
++            "By default port 16994 (SSL: 16995) is used.\n"
++#else
+             "By default port 16994 is used.\n"
++#endif
+           "If no password is given " APPNAME " will ask for one.\n"
+             "\n"
+             "-- \n"
+@@ -941,7 +953,7 @@ main(int argc, char *argv[])
+     fcntl(ConnectionNumber(dpy),F_SETFD,FD_CLOEXEC);
+ 
+     for (;;) {
+-        if (-1 == (c = getopt(argc, argv, "hdtu:p:f:c:b:l:")))
++        if (-1 == (c = getopt(argc, argv, "hdtu:p:f:c:b:l:LC:")))
+             break;
+         switch (c) {
+       case 'd':
+@@ -960,6 +972,14 @@ main(int argc, char *argv[])
+       case 'l':
+             log = optarg;
+           break;
++      case 'L':
++          amt_legacy = 1;
++          break;
++#if defined(USE_OPENSSL) || defined(USE_GNUTLS)
++      case 'C':
++          amt_cacert = optarg;
++          break;
++#endif
+ 
+       case 'f':
+           cfg_set_str(CFG_FONT, optarg);
blob - /dev/null
file + comms/amtterm/patches/patch-redir_c
--- /dev/null
+++ comms/amtterm/patches/patch-redir_c
@@ -0,0 +1,196 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: redir.c
+--- redir.c.orig
++++ redir.c
+@@ -29,9 +29,12 @@
+ #include <ctype.h>
+ #include <errno.h>
+ #include <fcntl.h>
++#include <sys/time.h>
+ 
+ #include "tcp.h"
++#include "ssl.h"
+ #include "redir.h"
++#include "auth.h"
+ 
+ static const char *state_name[] = {
+     [ REDIR_NONE      ] = "NONE",
+@@ -100,7 +103,7 @@ static ssize_t redir_write(struct redir *r, const char
+ 
+     if (r->trace)
+       hexdump("out", buf, count);
+-    rc = write(r->sock, buf, count);
++    rc = sslwrite(r->ctx, buf, count);
+     if (-1 == rc)
+       snprintf(r->err, sizeof(r->err), "write(socket): %s", strerror(errno));
+     return rc;
+@@ -142,8 +145,11 @@ const char *redir_state_desc(enum redir_state state)
+ int redir_connect(struct redir *r)
+ {
+     static unsigned char *defport = "16994";
++    static unsigned char *sslport = "16995";
+     struct addrinfo ai;
+ 
++    if (r->cacert)
++      defport = sslport;
+     memset(&ai, 0, sizeof(ai));
+     ai.ai_socktype = SOCK_STREAM;
+     ai.ai_family = PF_UNSPEC;
+@@ -151,6 +157,11 @@ int redir_connect(struct redir *r)
+     redir_state(r, REDIR_CONNECT);
+     r->sock = tcp_connect(&ai, NULL, NULL, r->host,
+                         strlen(r->port) ? r->port : defport);
++    r->ctx = sslinit(r->sock, r->cacert);
++    if(r->ctx == NULL) {
++      close(r->sock);
++      r->sock = -1;
++    }
+     if (-1 == r->sock) {
+         redir_state(r, REDIR_ERROR);
+         /* FIXME: better error message */
+@@ -179,11 +190,13 @@ int redir_stop(struct redir *r)
+ 
+     redir_state(r, REDIR_CLOSED);
+     redir_write(r, request, sizeof(request));
++    sslexit(r->ctx);
++    r->ctx = NULL;
+     close(r->sock);
+     return 0;
+ }
+ 
+-int redir_auth(struct redir *r)
++static int redir_auth_old(struct redir *r)
+ {
+     int ulen = strlen(r->user);
+     int plen = strlen(r->pass);
+@@ -205,6 +218,79 @@ int redir_auth(struct redir *r)
+     return rc;
+ }
+ 
++static int io(void *parm, unsigned char *data, int len, int mode)
++{
++    int rc;
++    struct redir *r;
++    struct timeval tv;
++    fd_set set;
++
++    switch(mode)
++    {
++    case READ:
++      r = (struct redir *)parm;
++      while (len) {
++          FD_ZERO(&set);
++          FD_SET(r->sock,&set);
++          if (!sslready(r->ctx)) {
++              tv.tv_sec  = HEARTBEAT_INTERVAL * 4 / 1000;
++              tv.tv_usec = 0;
++              switch (select(r->sock+1,&set,NULL,NULL,&tv)) {
++              case -1:
++                  perror("select");
++                  return -1;
++              case 0:
++                  fprintf(stderr,"select: timeout\n");
++                  return -1;
++              }
++          }
++          rc = sslread(r->ctx, data, len);
++          switch (rc) {
++          case -1:
++              fprintf(stderr, "read(socket): %s", strerror(errno));
++              return -1;
++          case 0:
++              fprintf(stderr, "EOF from socket");
++              return -1;
++          default:
++              if (r->trace)
++                  hexdump("in ", data, rc);
++              data += rc;
++              len -= rc;
++          }
++      }
++      return 0;
++
++    case WRITE:
++      r = (struct redir *)parm;
++      if (redir_write(r, data, len) != len)
++          return -1;
++      return 0;
++
++    case RANDOM:
++      gettimeofday(&tv, NULL);
++      if (sizeof(tv) <= len)
++          memcpy(data, &tv, sizeof(tv));
++      else
++          memcpy(data, &tv, len);
++      return 0;
++    }
++
++    return -1;
++}
++
++int redir_auth(struct redir *r)
++{
++    int rc;
++
++    if (r->legacy)
++      return redir_auth_old(r);
++
++    redir_state(r, REDIR_AUTH);
++    rc = authenticate(0, r->user, r->pass, io, r);
++    return rc;
++}
++
+ int redir_sol_start(struct redir *r)
+ {
+     unsigned char request[START_SOL_REDIRECTION_LENGTH] = {
+@@ -280,7 +366,7 @@ int redir_sol_recv(struct redir *r)
+          ready yet, but should be here Real Soon Now. */
+       flags = fcntl(r->sock,F_GETFL);
+       fcntl(r->sock,F_SETFL, flags & (~O_NONBLOCK));
+-      count = read(r->sock, msg, count);
++      count = sslread(r->ctx, msg, count);
+       fcntl(r->sock,F_SETFL, flags);
+ 
+       switch (count) {
+@@ -309,12 +395,13 @@ int redir_data(struct redir *r)
+ {
+     int rc, bshift;
+ 
++repeat:
+     if (r->trace) {
+       fprintf(stderr, "in --\n");
+       if (r->blen)
+           fprintf(stderr, "in : already have %d\n", r->blen);
+     }
+-    rc = read(r->sock, r->buf + r->blen, sizeof(r->buf) - r->blen);
++    rc = sslread(r->ctx, r->buf + r->blen, sizeof(r->buf) - r->blen);
+     switch (rc) {
+     case -1:
+       snprintf(r->err, sizeof(r->err), "read(socket): %s", strerror(errno));
+@@ -456,18 +543,24 @@ int redir_data(struct redir *r)
+       memmove(r->buf, r->buf + bshift, r->blen - bshift);
+       r->blen -= bshift;
+     }
++    if (r->ctx && sslready(r->ctx))
++      goto repeat;
+     return 0;
+ 
+ again:
+     /* need more data, jump back into poll/select loop */
+     if (r->trace)
+       fprintf(stderr, "in : need more data\n");
++    if (sslready(r->ctx))
++      goto repeat;
+     return 0;
+ 
+ err:
+     if (r->trace)
+       fprintf(stderr, "in : ERROR (%s)\n", r->err);
+     redir_state(r, REDIR_ERROR);
++    sslexit(r->ctx);
++    r->ctx = NULL;
+     close(r->sock);
+     return -1;
+ }
blob - /dev/null
file + comms/amtterm/patches/patch-redir_h
--- /dev/null
+++ comms/amtterm/patches/patch-redir_h
@@ -0,0 +1,23 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: redir.h
+--- redir.h.orig
++++ redir.h
+@@ -26,12 +26,16 @@ struct redir {
+     unsigned char     type[4];
+     int               verbose;
+     int               trace;
++    int               legacy;
+     enum redir_state  state;
+     unsigned char     err[128]; // state == REDIR_ERROR
+ 
+     int               sock;
+     unsigned char     buf[64];
+     unsigned int      blen;
++
++    void              *cacert;
++    void              *ctx;
+ 
+     /* callbacks */
+     void *cb_data;
blob - /dev/null
file + comms/amtterm/patches/patch-ssl_c
--- /dev/null
+++ comms/amtterm/patches/patch-ssl_c
@@ -0,0 +1,459 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: ssl.c
+--- ssl.c.orig
++++ ssl.c
+@@ -0,0 +1,452 @@
++/*
++ *  SSL helper functions.
++ *
++ *  Copyright (C) 2014 Andreas Steinmetz <a...@domdv.de>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or
++ *  (at your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful,
++ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ *  GNU General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License along
++ *  with this program; if not, write to the Free Software Foundation, Inc.,
++ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
++ */
++
++#include <unistd.h>
++#include <stdlib.h>
++#include <string.h>
++#include <stdio.h>
++
++#if defined(USE_OPENSSL)
++#include <openssl/ssl.h>
++#include <openssl/err.h>
++#elif defined(USE_GNUTLS)
++#include <gnutls/gnutls.h>
++#endif
++
++#include "ssl.h"
++
++struct ctx
++{
++      int fd;
++#if defined(USE_OPENSSL)
++      SSL *ssl;
++      SSL_CTX *ctx;
++#elif defined(USE_GNUTLS)
++      gnutls_session_t ssl;
++      gnutls_certificate_credentials_t cred;
++#endif
++};
++
++static struct ctx *newctx(int fd)
++{
++      struct ctx *ctx;
++
++      if(!(ctx=malloc(sizeof(struct ctx))))
++      {
++              perror("malloc");
++              return NULL;
++      }
++
++      memset(ctx,0,sizeof(struct ctx));
++
++      ctx->fd=fd;
++
++      return ctx;
++}
++
++#if defined(USE_OPENSSL)
++
++struct ctx *sslinit(int fd,char *cacert)
++{
++      int r;
++      int c=0;
++      struct ctx *ctx;
++
++      if(!(ctx=newctx(fd)))return NULL;
++
++      if(!cacert)return ctx;
++
++      SSL_load_error_strings();
++      SSL_library_init();
++
++      if(!(ctx->ctx=SSL_CTX_new(SSLv23_client_method())))
++      {
++              ERR_print_errors_fp(stderr);
++              goto err1;
++      }
++
++#if OPENSSL_VERSION_NUMBER >= 0x1000100FL
++      SSL_CTX_set_options(ctx->ctx,
++              SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
++#endif
++
++      if(!SSL_CTX_load_verify_locations(ctx->ctx,cacert,NULL))
++      {
++              ERR_print_errors_fp(stderr);
++              goto err2;
++      }
++
++      SSL_CTX_set_verify_depth(ctx->ctx,5);
++      SSL_CTX_set_verify(ctx->ctx,SSL_VERIFY_PEER,NULL);
++
++      if(!(ctx->ssl=SSL_new(ctx->ctx)))
++      {
++              ERR_print_errors_fp(stderr);
++              goto err2;
++      }
++
++      if(!SSL_set_fd(ctx->ssl,ctx->fd))
++      {
++              ERR_print_errors_fp(stderr);
++              goto err3;
++      }
++
++repeat:       if((r=SSL_connect(ctx->ssl))!=1)
++      {
++              switch(SSL_get_error(ctx->ssl,r))
++              {
++              case SSL_ERROR_WANT_READ:
++              case SSL_ERROR_WANT_WRITE:
++                      if(++c<100)
++                      {
++                              usleep(10000);
++                              goto repeat;
++                      }
++              }
++              ERR_print_errors_fp(stderr);
++              goto err3;
++      }
++
++      return ctx;
++
++err3: SSL_free(ctx->ssl);
++err2: SSL_CTX_free(ctx->ctx);
++err1: free(ctx);
++      return NULL;
++}
++
++void sslexit(struct ctx *ctx)
++{
++      if(ctx->ssl)
++      {
++              SSL_shutdown(ctx->ssl);
++              SSL_free(ctx->ssl);
++              SSL_CTX_free(ctx->ctx);
++      }
++      free(ctx);
++}
++
++int sslready(struct ctx *ctx)
++{
++      if(ctx->ssl)return SSL_pending(ctx->ssl);
++      else return 0;
++}
++
++ssize_t sslread(struct ctx *ctx,void *buf,size_t count)
++{
++      int l;
++      int c=0;
++
++      if(!ctx->ssl)return read(ctx->fd,buf,count);
++      if(!count)return 0;
++
++repeat:       if((l=SSL_read(ctx->ssl,buf,count))>0)return l;
++
++      switch(SSL_get_error(ctx->ssl,l))
++      {
++      case SSL_ERROR_WANT_READ:
++      case SSL_ERROR_WANT_WRITE:
++              if(++c<100)
++              {
++                      usleep(10000);
++                      goto repeat;
++              }
++              break;
++      case SSL_ERROR_WANT_X509_LOOKUP:
++              return -1;
++      case SSL_ERROR_ZERO_RETURN:
++              return 0;
++      case SSL_ERROR_SSL:
++              ERR_print_errors_fp(stderr);
++      }
++
++      return -1;
++}
++
++ssize_t sslwrite(struct ctx *ctx,const void *buf,size_t count)
++{
++      int l;
++      int c=0;
++
++      if(!ctx->ssl)return write(ctx->fd,buf,count);
++      if(!count)return 0;
++
++repeat:       if((l=SSL_write(ctx->ssl,buf,count))>0)return l;
++
++      switch(SSL_get_error(ctx->ssl,l))
++      {
++      case SSL_ERROR_WANT_READ:
++      case SSL_ERROR_WANT_WRITE:
++              if(++c<100)
++              {
++                      usleep(10000);
++                      goto repeat;
++              }
++              break;
++      case SSL_ERROR_WANT_X509_LOOKUP:
++              return -1;
++      case SSL_ERROR_ZERO_RETURN:
++              return 0;
++      case SSL_ERROR_SSL:
++              ERR_print_errors_fp(stderr);
++      }
++
++      return -1;
++}
++
++#elif defined(USE_GNUTLS)
++
++static int vrycb(gnutls_session_t ssl)
++{
++      int r;
++      int type;
++      unsigned int status;
++      gnutls_datum_t msg;
++
++      if((r=gnutls_certificate_verify_peers3(ssl,NULL,&status))<0)
++      {
++              fprintf(stderr,"gnutls_certificate_verify_peers3: %s\n",
++                      gnutls_strerror(r));
++              return GNUTLS_E_CERTIFICATE_ERROR;
++      }
++
++      if(status)
++      {
++              type=gnutls_certificate_type_get(ssl);
++              if((r=gnutls_certificate_verification_status_print(status,type,
++                      &msg,0))<0)
++              {
++                      fprintf(stderr,"gnutls_certificate_verification_"
++                              "status_print %s\n",gnutls_strerror(r));
++              }
++              else
++              {
++                      fprintf(stderr,"certificate status: %s\n",msg.data);
++                      gnutls_free(msg.data);
++              }
++              return GNUTLS_E_CERTIFICATE_ERROR;
++      }
++
++      return 0;
++}
++
++struct ctx *sslinit(int fd,char *cacert)
++{
++      int r;
++      const char *e;
++      struct ctx *ctx;
++
++      if(!(ctx=newctx(fd)))return NULL;
++
++      if(!cacert)return ctx;
++
++      if((r=gnutls_global_init()))
++      {
++              fprintf(stderr,"gnutls_global_init: %s\n",gnutls_strerror(r));
++              goto err1;
++      }
++
++      if((r=gnutls_certificate_allocate_credentials(&ctx->cred)))
++      {
++              fprintf(stderr,"gnutls_certificate_allocate_credentials: "
++                      "%s\n",gnutls_strerror(r));
++              goto err2;
++      }
++
++      if((r=gnutls_certificate_set_x509_trust_file(ctx->cred,cacert,
++              GNUTLS_X509_FMT_PEM))<0)
++      {
++              fprintf(stderr,"gnutls_certificate_set_x509_trust_file: "
++                      "%s\n",gnutls_strerror(r));
++              goto err3;
++      }
++
++      gnutls_certificate_set_verify_function(ctx->cred,vrycb);
++
++      if((r=gnutls_init(&ctx->ssl,GNUTLS_CLIENT)))
++      {
++              fprintf(stderr,"gnutls_init: %s\n",gnutls_strerror(r));
++              goto err3;
++      }
++
++      /* oh well, isn't _that_ easy ?!? :-(  ... compare to openssl ... */
++      if((r=gnutls_priority_set_direct(ctx->ssl,"NONE:+AES-256-CBC:"
++              "+AES-128-CBC:+3DES-CBC:+COMP-NULL:+CTYPE-X509:+VERS-SSL3.0:"
++              "+SHA256:+SHA1:+RSA:%UNSAFE_RENEGOTIATION",&e)))
++      {
++              fprintf(stderr,"gnutls_priority_set_direct: %s\n",
++                      gnutls_strerror(r));
++              if(r==GNUTLS_E_INVALID_REQUEST)
++                      fprintf(stderr,"additional info: %s\n",e);
++              goto err4;
++      }
++
++      if((r=gnutls_credentials_set(ctx->ssl,GNUTLS_CRD_CERTIFICATE,
++              ctx->cred)))
++      {
++              fprintf(stderr,"gnutls_credentials_set: %s\n",
++                      gnutls_strerror(r));
++              goto err4;
++      }
++
++      gnutls_transport_set_int(ctx->ssl,ctx->fd);
++
++      gnutls_handshake_set_timeout(ctx->ssl,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
++
++      do
++      {
++              r=gnutls_handshake(ctx->ssl);
++      } while(r<0&&!gnutls_error_is_fatal(r));
++      if(r<0)
++      {
++              fprintf(stderr,"gnutls_handshake: %s\n",gnutls_strerror(r));
++              goto err4;
++      }
++
++      return ctx;
++
++err4: gnutls_deinit(ctx->ssl);
++err3: gnutls_certificate_free_credentials(ctx->cred);
++err2: gnutls_global_deinit();
++err1: free(ctx);
++      return NULL;
++}
++
++void sslexit(struct ctx *ctx)
++{
++      if(ctx->ssl)
++      {
++              gnutls_deinit(ctx->ssl);
++              gnutls_certificate_free_credentials(ctx->cred);
++              gnutls_global_deinit();
++      }
++      free(ctx);
++}
++
++int sslready(struct ctx *ctx)
++{
++      if(ctx->ssl)return gnutls_record_check_pending(ctx->ssl);
++      else return 0;
++}
++
++ssize_t sslread(struct ctx *ctx,void *buf,size_t count)
++{
++      ssize_t l;
++      int c=0;
++      int r;
++
++      if(!ctx->ssl)return read(ctx->fd,buf,count);
++      if(!count)return 0;
++
++repeat:       if((l=gnutls_record_recv(ctx->ssl,buf,count))>0)return l;
++
++      switch(l)
++      {
++      case GNUTLS_E_REHANDSHAKE:
++              do
++              {
++                      r=gnutls_handshake(ctx->ssl);
++              } while(r<0&&!gnutls_error_is_fatal(r));
++              if(r<0)
++              {
++                      fprintf(stderr,"gnutls_handshake: %s\n",
++                      gnutls_strerror(r));
++                      return -1;
++              }
++      case GNUTLS_E_INTERRUPTED:
++      case GNUTLS_E_AGAIN:
++              if(++c<100)
++              {
++                      usleep(10000);
++                      goto repeat;
++              }
++      default:fprintf(stderr,"gnutls_record_recv: %s\n",gnutls_strerror(l));
++      case GNUTLS_E_PUSH_ERROR:
++      case GNUTLS_E_PULL_ERROR:
++              return -1;
++      }
++}
++
++ssize_t sslwrite(struct ctx *ctx,const void *buf,size_t count)
++{
++      ssize_t l;
++      int c=0;
++      int r;
++
++      if(!ctx->ssl)return write(ctx->fd,buf,count);
++      if(!count)return 0;
++
++repeat:       if((l=gnutls_record_send(ctx->ssl,buf,count))>0)return l;
++
++      switch(l)
++      {
++      case GNUTLS_E_REHANDSHAKE:
++              do
++              {
++                      r=gnutls_handshake(ctx->ssl);
++              } while(r<0&&!gnutls_error_is_fatal(r));
++              if(r<0)
++              {
++                      fprintf(stderr,"gnutls_handshake: %s\n",
++                      gnutls_strerror(r));
++                      return -1;
++              }
++      case GNUTLS_E_INTERRUPTED:
++      case GNUTLS_E_AGAIN:
++              if(++c<100)
++              {
++                      usleep(10000);
++                      goto repeat;
++              }
++      default:fprintf(stderr,"gnutls_record_send: %s\n",gnutls_strerror(l));
++      case GNUTLS_E_PUSH_ERROR:
++      case GNUTLS_E_PULL_ERROR:
++              return -1;
++      }
++}
++
++#else
++
++struct ctx *sslinit(int fd,char *cacert)
++{
++      return newctx(fd);
++}
++
++void sslexit(struct ctx *ctx)
++{
++      free(ctx);
++}
++
++int sslready(struct ctx *ctx)
++{
++      return 0;
++}
++
++ssize_t sslread(struct ctx *ctx,void *buf,size_t count)
++{
++      return read(ctx->fd,buf,count);
++}
++
++ssize_t sslwrite(struct ctx *ctx,const void *buf,size_t count)
++{
++      return write(ctx->fd,buf,count);
++}
++
++#endif
blob - /dev/null
file + comms/amtterm/patches/patch-ssl_h
--- /dev/null
+++ comms/amtterm/patches/patch-ssl_h
@@ -0,0 +1,14 @@
+$OpenBSD$
+Add support for SSL and digest auth required by newer versions of Intel ME.
+via https://github.com/Openwsman/wsmancli/issues/10#issuecomment-751253133
+Index: ssl.h
+--- ssl.h.orig
++++ ssl.h
+@@ -0,0 +1,7 @@
++struct ctx;
++
++extern struct ctx *sslinit(int fd,char *cacert);
++extern void sslexit(struct ctx *ctx);
++extern int sslready(struct ctx *ctx);
++extern ssize_t sslread(struct ctx *ctx,void *buf,size_t count);
++extern ssize_t sslwrite(struct ctx *ctx,const void *buf,size_t count);

Reply via email to