Changeset 11126 in ntrip


Ignore:
Timestamp:
Oct 24, 2026, 11:14:36 PM (18 hours ago)
Author:
stuerze
Message:

Some fixes from security point of view

Location:
trunk/BNC
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/CHANGELOG.md

    r11124 r11126  
    5454- FIXED: Memory corruption by stream content: VTEC messages with spherical harmonics degree or order 16 (IGS-SSR and RTCM-SSR; with 4 layers BNC crashed), RTCM-SSR metadata with more than 7 entries, names of 31 characters in RTCM 1300/1301/1302; range check of the VTEC parameters from the RTNet engine
    5555- FIXED: Password no longer sent in the request line (Ntrip Version 1 via proxy, RTSP) and no longer written to the log (RTSP)
     56- FIXED: Upload of CRS messages 1300/1302 (and encoding of 1301): names were sent padded to 31 characters, database links without their length field (unreadable for decoders); no CRS messages for a custom transformation
     57- FIXED: Upload via Ntrip 2s: 'Ignore SSL authorization errors' had no effect (handshake failed), and with it ticked no client certificate was presented; SSL errors are logged with their reason; for upload and download the ignored errors are logged; without OpenSSL run-time libraries no upload instead of an unencrypted Ntrip Version 2 upload
     58- FIXED: Encoding of new RTCM-SSR metadata with more than 30 additional parameter bits
     59- CHANGED: Help text of 'Ignore SSL authorization errors' explains that the server is then not authenticated
    5660
    5761## 2.13.7 (2026-07-31)
  • trunk/BNC/src/RTCM3/clock_and_orbit/clock_orbit_rtcm_new.cpp

    r11124 r11126  
    472472      for (i = 0; i < md->NumEntries; i++) {
    473473        E_MODEL_CORRECTION_TYPE_INDICATOR(md->Entries[i].TypeIndicator)
    474         E_ADDITIONAL_MODEL_PARAMETER_INDICATOR(md->Entries[i].ApplicationIndicator)
     474        E_MODEL_CORRECTION_APPLICATION_INDICATOR(md->Entries[i].ApplicationIndicator)
    475475        E_NON_DEFAULT_MODEL_CORRECTION_INDICATOR(md->Entries[i].nonDefaultIndicator)
    476476        if (md->Entries[i].nonDefaultIndicator) {
    … …  
    489489        if (md->Entries[i].nonDefaultIndicator &&
    490490            md->Entries[i].additionalParameterIndicator) {
    491           E_ADDITIONAL_MODEL_PARAMETER_DATA(md->Entries[i].additionalParameterData, md->Entries[i].additionalParameterNumBits)       
     491          /* up to 255 bits, only 32 stored (leading bits zero); in pieces of
     492             16 bits, as ADDBITS cannot handle more than 30 bits */
     493          unsigned int k = md->Entries[i].additionalParameterNumBits;
     494          while (k) {
     495            unsigned int n = (k > 16) ? 16 : k;
     496            k -= n;
     497            E_ADDITIONAL_MODEL_PARAMETER_DATA((k < 32) ? (md->Entries[i].additionalParameterData >> k) : 0, n)
     498          }
    492499      }
    493500    }
  • trunk/BNC/src/RTCM3/crsEncoder.cpp

    r10551 r11126  
    1111using namespace std;
    1212
     13// Length of a name for the 5-bit length field: up to the terminating 0,
     14// at most 31 characters
     15////////////////////////////////////////////////////////////////////////////
     16static int nameLength(const char* name, size_t bufSize) {
     17  size_t n = strnlen(name, bufSize);
     18  return (n > 31) ? 31 : int(n);
     19}
     20
    1321// build up RTCM3 for serviceCrs
    1422////////////////////////////////////////////////////////////////////////////
    … …  
    1725  INITBLOCK
    1826  ADDBITS(12, 1300)
    19   int N = sizeof(serviceCrs._name) / sizeof(serviceCrs._name[0]);
    20   if (N > 31) {N = 31;}
     27  int N = nameLength(serviceCrs._name, sizeof(serviceCrs._name));
    2128  ADDBITS(5, N)
    2229  for(int i = 0; i < N; i++) {
    … …  
    3542
    3643  ADDBITS(12, 1302)
    37   int N = sizeof(rtcmCrs._name) / sizeof(rtcmCrs._name[0]);
    38   if (N > 31) {N = 31;}
     44  int N = nameLength(rtcmCrs._name, sizeof(rtcmCrs._name));
    3945  ADDBITS(5, N)
    4046  for(int i = 0; i < N; i++) {
    … …  
    4450  ADDBITS(5, rtcmCrs._plateNumber)
    4551  int dblinknum = rtcmCrs._databaseLinks.size();
     52  if (dblinknum > 7) {dblinknum = 7;} // 3 bits
    4653  ADDBITS(3, dblinknum);
    47   if (dblinknum) {
    48     for(int d = 0; d < dblinknum; d++) {
    49       N = sizeof(rtcmCrs._databaseLinks[d]) / sizeof(rtcmCrs._databaseLinks[d][0]);
    50       for(int i = 0; i < N; i++) {
    51         ADDBITS(8, rtcmCrs._databaseLinks[d].toLatin1()[i])
    52       }
     54  for(int d = 0; d < dblinknum; d++) {
     55    QByteArray dblink = rtcmCrs._databaseLinks[d].toLatin1();
     56    N = nameLength(dblink.constData(), dblink.size());
     57    ADDBITS(5, N)
     58    for(int i = 0; i < N; i++) {
     59      ADDBITS(8, dblink[i])
    5360    }
    5461  }
    … …  
    6572
    6673  ADDBITS(12, 1301)
    67   int N = sizeof(helmertPar._sourceName) / sizeof(helmertPar._sourceName[0]);
    68   if (N > 31) {N = 31;}
     74  int N = nameLength(helmertPar._sourceName, sizeof(helmertPar._sourceName));
    6975  ADDBITS(5, N)
    7076  for(int i = 0; i < N; i++) {
    7177    ADDBITS(8, helmertPar._sourceName[i])
    7278  }
    73   N = sizeof(helmertPar._targetName) / sizeof(helmertPar._targetName[0]);
    74   if (N > 31) {N = 31;}
     79  N = nameLength(helmertPar._targetName, sizeof(helmertPar._targetName));
    7580  ADDBITS(5, N)
    7681  for(int i = 0; i < N; i++) {
  • trunk/BNC/src/bnchelp.html

    r11123 r11126  
    26842684    Broadcaster. </p>
    26852685  <p>
    2686     Tick 'Ignore SSL authorization errors' if you generally trust the server and do not want to be bothered with this.
     2686    Tick 'Ignore SSL authorization errors' to accept a server certificate that cannot be verified, e.g. a
     2687    self-signed certificate or one issued for another host name. The connection is then still encrypted, but the
     2688    server is not authenticated: anybody able to intercept the connection may receive your user name and password
     2689    and feed in manipulated data. The ignored errors are logged. Better save the CA certificate of the Ntrip
     2690    Broadcaster in the 'Path to SSL certificates' directory.
    26872691  </p>
    26882692  <p><img src="IMG/Figure07.png" width=800 /></p>
  • trunk/BNC/src/bncnetqueryv2.cpp

    r10984 r11126  
    286286    const QSslError& err = it.next();
    287287    msg += err.errorString();
    288   }
    289 
     288    if (it.hasNext()) {
     289      msg += "; ";
     290    }
     291  }
     292
     293  msg = _url.host() + ": " + msg;
    290294  if (_sslIgnoreErrors) {
    291295    _reply->ignoreSslErrors();
    292     BNC_CORE->slotMessage("BNC ignores SSL errors as configured", true);
     296    BNC_CORE->slotMessage((msg + " (ignored as configured)").toLatin1(), true);
    293297  }
    294298  else {
  • trunk/BNC/src/bncwindow.cpp

    r11110 r11126  
    15481548  _sslCaCertPathLineEdit->setWhatsThis(tr("<p>Communication with an Ntrip Broadcaster over SSL requires the exchange of server certificates. Specify the path to a directory where you save CA certificates on your system. </p><p>BNC creates from *.crt and *.pem files a CA certificate database, which is used by the socket during the handshake phase to validate the peer's certificate. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslCaCertPath]</i></p>"));
    15491549  _sslClientCertPathLineEdit->setWhatsThis(tr("<p>Two-sided communication with an Ntrip Broadcaster over SSL requires in addition the exchange of client certificates. Specify the full path to the client certificates on your system.</p><p></p><p>The file naming convention for client certificates in BNC is as follows: &lt;hostname&gt;.&lt;port&gt;.crt for the certificate and &lt;hostname&gt;.&lt;port&gt;.key for the private key, where &lt;hostname&gt; is without https://. </p><p> If available, the client or personal authentication certificate is presented to the peer during the SSL handshake process. Password protected key files are not supported. </p><p>Don't try communication via two sided SSL if you are not sure whether this is supported by the involved Ntrip Broadcaster. </p><p>Note that SSL communication is usually done over port 443. <i>[key: sslClientCertPath]</i></p>"));
    1550   _sslIgnoreErrorsCheckBox->setWhatsThis(tr("<p>SSL communication may involve queries coming from the Ntrip Broadcaster. Tick 'Ignore SSL authorization errors' if you don't want to be bothered with this. <i>[key: sslIgnoreErrors]</i></p>"));
     1550  _sslIgnoreErrorsCheckBox->setWhatsThis(tr("<p>Tick 'Ignore SSL authorization errors' to accept a server certificate that cannot be verified, e.g. a self-signed certificate or one issued for another host name. The connection is then still encrypted, but the server is not authenticated: anybody able to intercept the connection may receive your user name and password and feed in manipulated data. The ignored errors are logged. Better save the CA certificate of the Ntrip Broadcaster in the 'Path to SSL certificates' directory. <i>[key: sslIgnoreErrors]</i></p>"));
    15511551
    15521552  // WhatsThis, General
  • trunk/BNC/src/upload/bncrtnetuploadcaster.cpp

    r11124 r11126  
    10681068    // -----------
    10691069    QByteArray hlpBufferServiceCrs;
    1070     if (sizeof(serviceCrs._name) > 0) {
     1070    if (serviceCrs._name[0]) { // no CRS messages for a custom transformation
    10711071        if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
    10721072            memset(obuffer, 0, sizeof(obuffer));
    … …  
    10811081    // --------
    10821082    QByteArray hlpBufferRtcmCrs;
    1083     if (sizeof(rtcmCrs._name) > 0) {
     1083    if (rtcmCrs._name[0]) {
    10841084        if (fmod(epoTime.gpssec(), _samplRtcmCrs) == 0.0) {
    10851085            memset(obuffer, 0, sizeof(obuffer));
  • trunk/BNC/src/upload/bncuploadcaster.cpp

    r10753 r11126  
    8080  if (_ntripVersion == "2s") {
    8181    if (!QSslSocket::supportsSsl()) {
    82       emit(newMessage(
    83           "For SSL support please install OpenSSL run-time libraries: Ntrip Version 2 is tried",
    84           true));
    85       _ntripVersion == "2";
     82      // no fallback to Ntrip Version 2: user name and password would be sent
     83      // unencrypted although an encrypted connection was configured
     84      emit(newMessage(_mountpoint.toLatin1() + "@" + _casterOutHost.toLatin1() +
     85          ": No SSL support, please install OpenSSL run-time libraries: no upload", true));
    8686    } else {
    8787      _secure = true;
    … …  
    150150      const QSslError& err = it.next();
    151151      msg += err.errorString();
    152     }
    153     emit(newMessage(msg.toLatin1(), true));
     152      if (it.hasNext()) {
     153        msg += "; ";
     154      }
     155    }
     156    if (_sslIgnoreErrors) {
     157      _outSocket->ignoreSslErrors();
     158      msg += " (ignored as configured)";
     159    }
     160    emit(newMessage(_mountpoint.toLatin1() + "@" + _casterOutHost.toLatin1() + ": " + msg.toLatin1(), true));
    154161  }
    155162}
    … …  
    203210  }
    204211
     212  if (_ntripVersion == "2s" && !_secure) { // no SSL support, see constructor
     213    return;
     214  }
     215
    205216  if (_outSocket != 0 &&
    206217      _outSocket->state() == QAbstractSocket::ConnectedState) {
    … …  
    224235  _outSocket->setProxy(QNetworkProxy::NoProxy);
    225236
    226   if (_sslIgnoreErrors) {
    227     _outSocket->ignoreSslErrors();
    228   } else {
    229     bncSslConfig sslConfig = BNC_SSL_CONFIG;
    230     QFile clientCrtFile(_crtFileName);
    231     QFile privateKeyFile(_keyFileName);
    232     if ( clientCrtFile.exists() && privateKeyFile.exists()) {
    233       // set local certificate
    234       clientCrtFile.open(QIODevice::ReadOnly);
    235       QSslCertificate clientCrt(&clientCrtFile);
    236       sslConfig.setLocalCertificate(clientCrt);
    237       // set private key if available
    238       privateKeyFile.open(QIODevice::ReadOnly);
    239       QSslKey privateKey(&privateKeyFile, QSsl::Rsa);
    240       sslConfig.setPrivateKey(privateKey);
    241     }
    242     _outSocket->setSslConfiguration(sslConfig);
    243     connect(_outSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>)));
    244   }
     237  bncSslConfig sslConfig = BNC_SSL_CONFIG;
     238  QFile clientCrtFile(_crtFileName);
     239  QFile privateKeyFile(_keyFileName);
     240  if ( clientCrtFile.exists() && privateKeyFile.exists()) {
     241    // set local certificate
     242    clientCrtFile.open(QIODevice::ReadOnly);
     243    QSslCertificate clientCrt(&clientCrtFile);
     244    sslConfig.setLocalCertificate(clientCrt);
     245    // set private key if available
     246    privateKeyFile.open(QIODevice::ReadOnly);
     247    QSslKey privateKey(&privateKeyFile, QSsl::Rsa);
     248    sslConfig.setPrivateKey(privateKey);
     249  }
     250  _outSocket->setSslConfiguration(sslConfig);
     251  // Direct connection: the socket lives in this thread, the caster object in
     252  // the main thread. The slot must run during the handshake, both for
     253  // ignoreSslErrors() to take effect and to access _outSocket safely.
     254  connect(_outSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>)),
     255          Qt::DirectConnection);
    245256
    246257  if (!_proxy) {
Note: See TracChangeset for help on using the changeset viewer.