Changeset 11128 in ntrip


Ignore:
Timestamp:
Oct 24, 2026, 11:37:52 PM (11 hours ago)
Author:
stuerze
Message:

Some fixes from security point of view

Location:
trunk/BNC
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/BNC/CHANGELOG.md

    r11126 r11128  
    5858- FIXED: Encoding of new RTCM-SSR metadata with more than 30 additional parameter bits
    5959- CHANGED: Help text of 'Ignore SSL authorization errors' explains that the server is then not authenticated
     60- CHANGED: UDP and RTSP/RTP streams: datagrams are accepted only from the Ntrip Broadcaster; streams without Ntrip ('UN') accept only the sender given as host in the stream URL, any sender with 127.0.0.1 (as written by 'Add Stream - Coming from UDP Port')
     61- CHANGED: The configuration file (contains passwords) is saved readable for the owner only
     62- FIXED: Upload: any caster answer containing '200' (e.g. in a header of a rejection) was taken as success; now the status line is checked
     63- FIXED: Raw file input (--file): a station ID with a path led to output files outside the output directory; invalid chunk sizes are rejected
    6064
    6165## 2.13.7 (2026-07-31)
  • trunk/BNC/src/bnchelp.html

    r11126 r11128  
    1032110321    Streams directly received at a UDP port show up with a 'UN' for 'UDP, No Ntrip' in the 'Streams' canvas section on
    1032210322    BNC's main window. Latitude and longitude are to be entered just for informal reasons.
     10323  </p>
     10324  <p>
     10325    BNC accepts the UDP datagrams of any sender at that port, so anybody able to reach it can feed in data. To accept
     10326    only the datagrams of one sender, replace '127.0.0.1' in the stream's URL ('mountPoints' option, e.g.
     10327    '//127.0.0.1:2101/FFMJ00DEU ...') by the sender's IP address or host name, e.g. '//192.168.1.20:2101/FFMJ00DEU ...'.
     10328    In the Ntrip modes 'U' (UDP) and 'R' (RTSP/RTP), BNC accepts datagrams only from the Ntrip Broadcaster.
    1032310329  <p>
    1032410330
  • trunk/BNC/src/bncnetqueryrtp.cpp

    r11124 r11128  
    7777void bncNetQueryRtp::waitForReadyRead(QByteArray& outData) {
    7878
    79   // Wait Loop
    80   // ---------
    81   if (!_udpSocket->hasPendingDatagrams()) {
    82     _eventLoop->exec();
    83   }
    84 
    85   // Append Data
    86   // -----------
    87   QByteArray datagram;
    88   datagram.resize(_udpSocket->pendingDatagramSize());
    89   _udpSocket->readDatagram(datagram.data(), datagram.size());
    90 
    91   if (datagram.size() > 12) {
    92     outData.append(datagram.mid(12));
     79  while (true) {
     80
     81    // Wait Loop
     82    // ---------
     83    if (!_udpSocket->hasPendingDatagrams()) {
     84      _eventLoop->exec();
     85      if (!_udpSocket->hasPendingDatagrams()) { // stopped
     86        return;
     87      }
     88    }
     89
     90    // Append Data, only from the RTSP server (anybody else could feed in data)
     91    // ------------------------------------------------------------------------
     92    QByteArray datagram;
     93    QHostAddress sender;
     94    datagram.resize(_udpSocket->pendingDatagramSize());
     95    _udpSocket->readDatagram(datagram.data(), datagram.size(), &sender);
     96    if (!sender.isEqual(_serverAddress, QHostAddress::ConvertV4MappedToIPv4)) {
     97      continue;
     98    }
     99
     100    if (datagram.size() > 12) {
     101      outData.append(datagram.mid(12));
     102    }
     103    return;
    93104  }
    94105}
    … …  
    126137  // --------------
    127138  if (_socket->waitForConnected(timeOut)) {
     139    _serverAddress = _socket->peerAddress();
    128140    QString uName = QUrl::fromPercentEncoding(_url.userName().toLatin1());
    129141    QString passW = QUrl::fromPercentEncoding(_url.password().toLatin1());
  • trunk/BNC/src/bncnetqueryrtp.h

    r8252 r11128  
    22#define BNCNETQUERYRTP_H
    33
     4#include <QHostAddress>
    45#include <QUdpSocket>
    56
    … …  
    2728  QByteArray  _session;
    2829  int         _CSeq;
     30  QHostAddress _serverAddress; // RTP data accepted only from here
    2931};
    3032
  • trunk/BNC/src/bncnetqueryudp.cpp

    r9961 r11128  
    7575void bncNetQueryUdp::waitForReadyRead(QByteArray& outData) {
    7676
    77   // Wait Loop
    78   // ---------
    79   if (!_udpSocket->hasPendingDatagrams()) {
    80     _eventLoop->exec();
    81   }
     77  while (true) {
    8278
    83   // Append Data
    84   // -----------
    85   QByteArray datagram;
    86   datagram.resize(_udpSocket->pendingDatagramSize());
    87   _udpSocket->readDatagram(datagram.data(), datagram.size());
     79    // Wait Loop
     80    // ---------
     81    if (!_udpSocket->hasPendingDatagrams()) {
     82      _eventLoop->exec();
     83      if (!_udpSocket->hasPendingDatagrams()) { // stopped
     84        return;
     85      }
     86    }
    8887
    89   if (datagram.size() > 12) {
    90     outData.append(datagram.mid(12));
    91   }
    92   else {
    93     _status = error;
     88    // Append Data, only from the caster (anybody else could feed in data)
     89    // -------------------------------------------------------------------
     90    QByteArray datagram;
     91    QHostAddress sender;
     92    datagram.resize(_udpSocket->pendingDatagramSize());
     93    _udpSocket->readDatagram(datagram.data(), datagram.size(), &sender);
     94    if (!sender.isEqual(_address, QHostAddress::ConvertV4MappedToIPv4)) {
     95      continue;
     96    }
     97
     98    if (datagram.size() > 12) {
     99      outData.append(datagram.mid(12));
     100    }
     101    else {
     102      _status = error;
     103    }
     104    return;
    94105  }
    95106}
    … …  
    156167
    157168    _udpSocket->writeDatagram(rtpbuffer, 12 + reqStr.size(), _address, _port);
     169    free(rtpbuffer);
    158170
    159171    // Wait for Reply, read Session Number
  • trunk/BNC/src/bncnetqueryudp0.cpp

    r6787 r11128  
    1414 *
    1515 * -----------------------------------------------------------------------*/
     16
     17#include <QHostInfo>
    1618
    1719#include "bncnetqueryudp0.h"
    … …  
    4749void bncNetQueryUdp0::waitForReadyRead(QByteArray& outData) {
    4850
    49   // Wait Loop
    50   // ---------
    51   if (!_udpSocket->hasPendingDatagrams()) {
    52     _eventLoop->exec();
     51  if (!_udpSocket) {
     52    return;
    5353  }
    5454
    55   // Append Data
    56   // -----------
    57   QByteArray datagram;
    58   datagram.resize(_udpSocket->pendingDatagramSize());
    59   _udpSocket->readDatagram(datagram.data(), datagram.size());
     55  while (true) {
    6056
    61   outData.append(datagram);
     57    // Wait Loop
     58    // ---------
     59    if (!_udpSocket->hasPendingDatagrams()) {
     60      _eventLoop->exec();
     61      if (!_udpSocket->hasPendingDatagrams()) { // stopped
     62        return;
     63      }
     64    }
     65
     66    // Append Data, only from the accepted senders
     67    // -------------------------------------------
     68    QByteArray datagram;
     69    QHostAddress sender;
     70    datagram.resize(_udpSocket->pendingDatagramSize());
     71    _udpSocket->readDatagram(datagram.data(), datagram.size(), &sender);
     72    bool accepted = _senders.isEmpty();
     73    for (int ii = 0; !accepted && ii < _senders.size(); ii++) {
     74      accepted = sender.isEqual(_senders[ii], QHostAddress::ConvertV4MappedToIPv4);
     75    }
     76    if (accepted) {
     77      outData.append(datagram);
     78      return;
     79    }
     80  }
    6281}
    6382
    … …  
    6786
    6887  _status = running;
     88
     89  // Host of the URL: sender whose datagrams are accepted; 127.0.0.1 (as
     90  // written by the 'Add Stream - Coming from UDP Port' dialog), localhost
     91  // or 0.0.0.0: datagrams from any sender
     92  _senders.clear();
     93  QString host = url.host();
     94  if (!host.isEmpty() && host != "127.0.0.1" && host != "localhost" && host != "0.0.0.0") {
     95    QHostAddress address;
     96    if (address.setAddress(host)) {
     97      _senders << address;
     98    }
     99    else {
     100      _senders = QHostInfo::fromName(host).addresses();
     101      if (_senders.isEmpty()) {
     102        emit newMessage(url.path().toLatin1().replace(0,1,"") +
     103                        ": Cannot resolve UDP sender " + host.toLatin1(), true);
     104        _status = error;
     105        return;
     106      }
     107    }
     108  }
    69109
    70110  delete _udpSocket;
  • trunk/BNC/src/bncnetqueryudp0.h

    r8252 r11128  
    22#define BNCNETQUERYUDP0_H
    33
     4#include <QHostAddress>
     5#include <QList>
    46#include <QUdpSocket>
    57
    … …  
    2022  QUdpSocket*  _udpSocket;
    2123  QEventLoop*  _eventLoop;
     24  QList<QHostAddress> _senders; // accepted senders, empty: any
    2225};
    2326
  • trunk/BNC/src/bncrawfile.cpp

    r11021 r11128  
    138138      BNC_CORE->setDateAndTimeGPS(QDateTime(QDateTime::fromString(lst.value(0), Qt::ISODate)));
    139139     
     140      // the station ID becomes part of output file names: no path separators
    140141      _staID  = lst.value(1).toLatin1();
     142      for (int ii = 0; ii < _staID.size(); ii++) {
     143        if (_staID[ii] == '/' || _staID[ii] == '\\' || (unsigned char)_staID[ii] < 0x20) {
     144          _staID[ii] = '_';
     145        }
     146      }
    141147      _format = lst.value(2).toLatin1();
    142       int nBytes = lst.value(3).toInt();
    143      
     148      bool ok;
     149      int nBytes = lst.value(3).trimmed().toInt(&ok);
     150      if (!ok || nBytes < 0 || nBytes > (1 << 24)) {
     151        BNC_CORE->slotMessage("Raw file: invalid chunk header: " + line.trimmed().left(80).toLatin1(), true);
     152        return data;
     153      }
     154
    144155      data = _inpFile->read(nBytes);
    145156     
  • trunk/BNC/src/bncsettings.cpp

    r11087 r11128  
    1515 * -----------------------------------------------------------------------*/
    1616
     17#include <QFile>
    1718#include <QSettings>
    1819
    … …  
    272273
    273274    settings.sync();
    274 }
     275
     276    // The file contains passwords: readable for the owner only
     277    QFile::setPermissions(BNC_CORE->confFileName(), QFile::ReadOwner | QFile::WriteOwner);
     278}
  • trunk/BNC/src/upload/bncuploadcaster.cpp

    r11126 r11128  
    2424
    2525using namespace std;
     26
     27// Status line of the caster/proxy answer is "HTTP/1.x 200 ..." or "ICY 200 OK"
     28////////////////////////////////////////////////////////////////////////////
     29static bool statusOk(const QByteArray& ans) {
     30  QList<QByteArray> status = ans.left(ans.indexOf("\r\n")).split(' ');
     31  return status.size() >= 2 && status[1] == "200" &&
     32         (status[0].startsWith("HTTP/") || status[0] == "ICY");
     33}
    2634
    2735// Constructor
    … …  
    284292
    285293      QByteArray ans = _outSocket->readAll();
    286       if (ans.indexOf("200") == -1) {
     294      if (!statusOk(ans)) {
    287295        int l = ans.indexOf("\r\n", 0);
    288296        emit(newMessage("Proxy: Connection broken for " + _mountpoint.toLatin1() + "@" +
    … …  
    331339   QByteArray ans = _outSocket->readAll();
    332340
    333   if (ans.indexOf("200") == -1) {
     341  if (!statusOk(ans)) {
    334342    delete _outSocket; _outSocket = 0;
    335343    int l = ans.indexOf("\r\n", 0);
Note: See TracChangeset for help on using the changeset viewer.