├── .gitignore ├── .gitmodules ├── .travis.yml ├── AUTHORS ├── COPYING ├── ChangeLog ├── Globals ├── Globals.cpp ├── Globals.h ├── GrabRepoInfo.sh └── Makefile.am ├── INSTALL ├── Makefile.am ├── Makefile.common ├── NEWS ├── README ├── SubscriberRegistry.cpp ├── SubscriberRegistry.h ├── apps ├── Makefile.am ├── checkdb.sh ├── comp128.c ├── hexmapper ├── sipauthserve.cpp └── syslogextractor ├── autogen.sh ├── config ├── Makefile.am └── pkg.m4 ├── configFiles ├── odbc.ini └── odbcinst.ini ├── configure.ac ├── debian ├── changelog ├── compat ├── control ├── dirs ├── links ├── postinst ├── postrm ├── preinst ├── prerm ├── rules └── sipauthserve.upstart ├── package ├── after-install-deb.sh ├── after-install-rpm.sh ├── build.sh ├── inputs └── pre-uninstall.sh ├── regs.gawk ├── regs.sh ├── servershare.cpp ├── servershare.h ├── test.SubscriberRegistry ├── Makefile ├── output.exp ├── runtest ├── sr.db.init ├── test.cpp ├── test.db.init1 └── test.db.init2 └── test.sipauthserve ├── exit.txt ├── output.exp ├── query.sql ├── register1.txt ├── register2.txt ├── register3.txt ├── register4.txt ├── register4a.txt ├── register4b.txt ├── register5.txt ├── register5a.txt ├── register5b.txt ├── register6.txt ├── runtest ├── sipauthserve.db.init ├── sr.db.init └── usender.pl /.gitignore: -------------------------------------------------------------------------------- 1 | ._* 2 | *.a 3 | *.o 4 | *.la 5 | *.lo 6 | .deps 7 | .libs 8 | Makefile 9 | Makefile.in 10 | depcomp 11 | install-sh 12 | missing 13 | aclocal.m4 14 | autom4te.cache/ 15 | build-arch-stamp 16 | build-indep-stamp 17 | config.guess 18 | config.h 19 | config.h.in 20 | config.log 21 | config.status 22 | config.sub 23 | configure 24 | configure-stamp 25 | debian/debhelper.log 26 | debian/files 27 | debian/substvars 28 | debian/tmp/ 29 | debian/sipauthserve.debhelper.log 30 | debian/sipauthserve.substvars 31 | debian/sipauthserve/ 32 | config.h.in~ 33 | libtool 34 | ltmain.sh 35 | stamp-h1 36 | apps/comp128 37 | apps/sipauthserve 38 | apps/subscriberRegistry.example.sql 39 | apps/sipauthserve.example.sql 40 | sipauthserve.example.sql 41 | package/tmp 42 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "CommonLibs"] 2 | path = CommonLibs 3 | url = https://github.com/RangeNetworks/CommonLibs.git 4 | branch = master 5 | [submodule "NodeManager"] 6 | path = NodeManager 7 | url = https://github.com/RangeNetworks/NodeManager.git 8 | branch = master 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | compiler: gcc 3 | 4 | notifications: 5 | irc: 6 | channels: 7 | - "chat.freenode.net#openbts" 8 | template: 9 | - "%{repository} : %{message} : %{build_url}" 10 | on_success: change 11 | on_failure: always 12 | 13 | git: 14 | submodules: false 15 | 16 | before_install: 17 | - sudo apt-get install -qq libosip2-dev 18 | - git clone https://github.com/RangeNetworks/libcoredumper.git 19 | - cd libcoredumper 20 | - ./build.sh 21 | - sudo dpkg -i *.deb 22 | - cd .. 23 | - git submodule update --init --recursive 24 | - sudo ./NodeManager/install_libzmq.sh 25 | 26 | #install: 27 | # - sh bootstrap.sh 28 | 29 | script: 30 | - dpkg-buildpackage -us -uc 31 | 32 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RangeNetworks/subscriberRegistry/c65b5d59f744a8df5f3395e217f2598f53e9fe65/AUTHORS -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RangeNetworks/subscriberRegistry/c65b5d59f744a8df5f3395e217f2598f53e9fe65/ChangeLog -------------------------------------------------------------------------------- /Globals/Globals.cpp: -------------------------------------------------------------------------------- 1 | /**@file Global system parameters. */ 2 | /* 3 | * Copyright 2013, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under multiple licenses; 6 | * see the COPYING file in the main directory for licensing 7 | * information for this specific distribuion. 8 | * 9 | * This use of this software may be subject to additional restrictions. 10 | * See the LEGAL file in the main directory for details. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 | 16 | */ 17 | 18 | /* 19 | This file keeps global system parameters. 20 | */ 21 | 22 | #include "config.h" 23 | #include 24 | 25 | const char *gVersionString = "release " VERSION " built " TIMESTAMP_ISO " " REPO_REV " "; 26 | -------------------------------------------------------------------------------- /Globals/Globals.h: -------------------------------------------------------------------------------- 1 | /**@file Global system parameters. */ 2 | /* 3 | * Copyright 2013, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under multiple licenses; 6 | * see the COPYING file in the main directory for licensing 7 | * information for this specific distribuion. 8 | * 9 | * This use of this software may be subject to additional restrictions. 10 | * See the LEGAL file in the main directory for details. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 | 16 | */ 17 | 18 | /* 19 | This file keeps global system parameters. 20 | */ 21 | 22 | #ifndef GLOBALS_H 23 | #define GLOBALS_H 24 | 25 | #include 26 | 27 | 28 | /** 29 | Just about everything goes into the configuration table. 30 | This should be defined in the main body of the top-level application. 31 | */ 32 | extern ConfigurationTable gConfig; 33 | 34 | /** The version string. */ 35 | extern const char *gVersionString; 36 | #endif 37 | -------------------------------------------------------------------------------- /Globals/GrabRepoInfo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This software is distributed under the terms of the GNU Public License. 6 | # See the COPYING file in the main directory for details. 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | # 21 | 22 | cd $1 23 | 24 | INFO="" 25 | if [ -d ./.svn ]; then 26 | INFO="r$(svn info . | grep "Last Changed Rev:" | cut -d " " -f 4) CommonLibs:r$(svn info ./CommonLibs | grep "Last Changed Rev:" | cut -d " " -f 4)" 27 | elif [ -d ./.git ]; then 28 | INFO="$(git rev-parse --short=10 HEAD) CommonLibs:$(cd CommonLibs; git rev-parse --short=10 HEAD)" 29 | fi 30 | 31 | echo $INFO 32 | -------------------------------------------------------------------------------- /Globals/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008 Free Software Foundation, Inc. 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This software is distributed under the terms of the GNU Public License. 6 | # See the COPYING file in the main directory for details. 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | # 21 | 22 | include $(top_srcdir)/Makefile.common 23 | 24 | noinst_LTLIBRARIES = libglobals.la 25 | 26 | libglobals_la_SOURCES = Globals.cpp 27 | 28 | noinst_PROGRAMS = 29 | 30 | noinst_HEADERS = Globals.h 31 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 5 | 2006, 2007, 2008, 2009 Free Software Foundation, Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell commands `./configure; make; make install' should 16 | configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 230 | parse its `' header file. The option `-nodtk' can be used as 231 | a workaround. If GNU CC is not installed, it is therefore recommended 232 | to try 233 | 234 | ./configure CC="cc" 235 | 236 | and if that doesn't work, try 237 | 238 | ./configure CC="cc -nodtk" 239 | 240 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 241 | directory contains several dysfunctional programs; working variants of 242 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 243 | in your `PATH', put it _after_ `/usr/bin'. 244 | 245 | On Haiku, software installed for all users goes in `/boot/common', 246 | not `/usr/local'. It is recommended to use the following options: 247 | 248 | ./configure --prefix=/boot/common 249 | 250 | Specifying the System Type 251 | ========================== 252 | 253 | There may be some features `configure' cannot figure out 254 | automatically, but needs to determine by the type of machine the package 255 | will run on. Usually, assuming the package is built to be run on the 256 | _same_ architectures, `configure' can figure that out, but if it prints 257 | a message saying it cannot guess the machine type, give it the 258 | `--build=TYPE' option. TYPE can either be a short name for the system 259 | type, such as `sun4', or a canonical name which has the form: 260 | 261 | CPU-COMPANY-SYSTEM 262 | 263 | where SYSTEM can have one of these forms: 264 | 265 | OS 266 | KERNEL-OS 267 | 268 | See the file `config.sub' for the possible values of each field. If 269 | `config.sub' isn't included in this package, then this package doesn't 270 | need to know the machine type. 271 | 272 | If you are _building_ compiler tools for cross-compiling, you should 273 | use the option `--target=TYPE' to select the type of system they will 274 | produce code for. 275 | 276 | If you want to _use_ a cross compiler, that generates code for a 277 | platform different from the build platform, you should specify the 278 | "host" platform (i.e., that on which the generated programs will 279 | eventually be run) with `--host=TYPE'. 280 | 281 | Sharing Defaults 282 | ================ 283 | 284 | If you want to set default values for `configure' scripts to share, 285 | you can create a site shell script called `config.site' that gives 286 | default values for variables like `CC', `cache_file', and `prefix'. 287 | `configure' looks for `PREFIX/share/config.site' if it exists, then 288 | `PREFIX/etc/config.site' if it exists. Or, you can set the 289 | `CONFIG_SITE' environment variable to the location of the site script. 290 | A warning: not all `configure' scripts look for a site script. 291 | 292 | Defining Variables 293 | ================== 294 | 295 | Variables not defined in a site shell script can be set in the 296 | environment passed to `configure'. However, some packages may run 297 | configure again during the build, and the customized values of these 298 | variables may be lost. In order to avoid this problem, you should set 299 | them in the `configure' command line, using `VAR=value'. For example: 300 | 301 | ./configure CC=/usr/local2/bin/gcc 302 | 303 | causes the specified `gcc' to be used as the C compiler (unless it is 304 | overridden in the site shell script). 305 | 306 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 307 | an Autoconf bug. Until the bug is fixed you can use this workaround: 308 | 309 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 310 | 311 | `configure' Invocation 312 | ====================== 313 | 314 | `configure' recognizes the following options to control how it 315 | operates. 316 | 317 | `--help' 318 | `-h' 319 | Print a summary of all of the options to `configure', and exit. 320 | 321 | `--help=short' 322 | `--help=recursive' 323 | Print a summary of the options unique to this package's 324 | `configure', and exit. The `short' variant lists options used 325 | only in the top level, while the `recursive' variant lists options 326 | also present in any nested packages. 327 | 328 | `--version' 329 | `-V' 330 | Print the version of Autoconf used to generate the `configure' 331 | script, and exit. 332 | 333 | `--cache-file=FILE' 334 | Enable the cache: use and save the results of the tests in FILE, 335 | traditionally `config.cache'. FILE defaults to `/dev/null' to 336 | disable caching. 337 | 338 | `--config-cache' 339 | `-C' 340 | Alias for `--cache-file=config.cache'. 341 | 342 | `--quiet' 343 | `--silent' 344 | `-q' 345 | Do not print messages saying which checks are being made. To 346 | suppress all normal output, redirect it to `/dev/null' (any error 347 | messages will still be shown). 348 | 349 | `--srcdir=DIR' 350 | Look for the package's source code in directory DIR. Usually 351 | `configure' can determine that directory automatically. 352 | 353 | `--prefix=DIR' 354 | Use DIR as the installation prefix. *note Installation Names:: 355 | for more details, including other options available for fine-tuning 356 | the installation locations. 357 | 358 | `--no-create' 359 | `-n' 360 | Run the configure checks, but stop before creating any output 361 | files. 362 | 363 | `configure' also accepts some other, not widely useful, options. Run 364 | `configure --help' for more details. 365 | 366 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008 Free Software Foundation, Inc. 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This software is distributed under the terms of the GNU Public License. 6 | # See the COPYING file in the main directory for details. 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | # 21 | 22 | include $(top_srcdir)/Makefile.common 23 | 24 | DESTDIR ?= 25 | # must be kept in sync with AC_CONFIG_MACRO_DIR in configure.ac 26 | ACLOCAL_AMFLAGS = -I config 27 | 28 | noinst_LTLIBRARIES = libSR.la 29 | 30 | libSR_la_SOURCES = \ 31 | SubscriberRegistry.cpp 32 | 33 | noinst_HEADERS = \ 34 | SubscriberRegistry.h 35 | 36 | # Order must be preserved 37 | SUBDIRS = \ 38 | config \ 39 | CommonLibs \ 40 | Globals \ 41 | NodeManager \ 42 | apps 43 | 44 | FORCE: 45 | -------------------------------------------------------------------------------- /Makefile.common: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008 Free Software Foundation, Inc. 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This software is distributed under the terms of the GNU Public License. 6 | # See the COPYING file in the main directory for details. 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | # 21 | 22 | # must be kept in sync with AC_CONFIG_MACRO_DIR in configure.ac 23 | # ACLOCAL_AMFLAGS = -I config 24 | 25 | AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) 26 | AM_CXXFLAGS := -Wall -pthread -ldl -DTIMESTAMP_ISO=`date +'"%Y-%m-%dT%H:%M:%S"'` 27 | 28 | REPOREV = -D'REPO_REV="$(shell ./$(top_builddir)/Globals/GrabRepoInfo.sh $(top_builddir))"' 29 | 30 | COMMON_INCLUDEDIR = $(top_srcdir)/CommonLibs 31 | GLOBALS_INCLUDEDIR = $(top_srcdir)/Globals 32 | NODEMANAGER_INCLUDEDIR = $(top_srcdir)/NodeManager 33 | JSONBOX_INCLUDEDIR = $(top_srcdir)/NodeManager/JsonBox-0.4.3/include 34 | JSONDB_INCLUDEDIR = $(top_srcdir)/NodeManager/JSONDB 35 | 36 | STD_DEFINES_AND_INCLUDES = \ 37 | $(REPOREV) \ 38 | -I$(COMMON_INCLUDEDIR) \ 39 | -I$(GLOBALS_INCLUDEDIR) \ 40 | -I$(NODEMANAGER_INCLUDEDIR) \ 41 | -I$(JSONBOX_INCLUDEDIR) \ 42 | -I$(JSONDB_INCLUDEDIR) 43 | 44 | # These macros are referenced in apps/Makefile.am, which must be changed in sync with these. 45 | COMMON_LA = $(top_builddir)/CommonLibs/libcommon.la 46 | GLOBALS_LA = $(top_builddir)/Globals/libglobals.la 47 | NODEMANAGER_LA = $(top_builddir)/NodeManager/libnodemanager.la -lzmq 48 | 49 | MOSTLYCLEANFILES = *~ 50 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RangeNetworks/subscriberRegistry/c65b5d59f744a8df5f3395e217f2598f53e9fe65/NEWS -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RangeNetworks/subscriberRegistry/c65b5d59f744a8df5f3395e217f2598f53e9fe65/README -------------------------------------------------------------------------------- /SubscriberRegistry.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Kestrel Signal Processing, Inc. 3 | * Copyright 2011, 2012, 2013, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under the terms of the GNU Affero Public License. 6 | * See the COPYING file in the main directory for details. 7 | * 8 | * This use of this software may be subject to additional restrictions. 9 | * See the LEGAL file in the main directory for details. 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU Affero General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Affero General Public License for more details. 20 | 21 | You should have received a copy of the GNU Affero General Public License 22 | along with this program. If not, see . 23 | 24 | */ 25 | 26 | #include "SubscriberRegistry.h" 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "sqlite3.h" 33 | #include 34 | #include 35 | #include 36 | #include // for sort() 37 | #include 38 | 39 | extern ConfigurationTable gConfig; 40 | 41 | 42 | using namespace std; 43 | 44 | static const char* createRRLPTable = { 45 | "CREATE TABLE IF NOT EXISTS RRLP (" 46 | "id INTEGER PRIMARY KEY, " 47 | "name VARCHAR(80) not null, " 48 | "latitude real not null, " 49 | "longitude real not null, " 50 | "error real not null, " 51 | "time text not null " 52 | ")" 53 | }; 54 | 55 | static const char* createDDTable = { 56 | "CREATE TABLE IF NOT EXISTS DIALDATA_TABLE (" 57 | "id INTEGER PRIMARY KEY, " 58 | "exten VARCHAR(40) NOT NULL DEFAULT '', " 59 | "dial VARCHAR(128) NOT NULL DEFAULT '' " 60 | ")" 61 | }; 62 | 63 | static const char* createRateTable = { 64 | "create table if not exists rates (service varchar(30) not null, rate integer not null)" 65 | }; 66 | 67 | static const char* createSBTable = { 68 | "CREATE TABLE IF NOT EXISTS SIP_BUDDIES (" 69 | "id integer primary key, " 70 | "name VARCHAR(80) not null, " 71 | "context VARCHAR(80), " 72 | "callingpres VARCHAR(30) DEFAULT 'allowed_not_screened', " 73 | "deny VARCHAR(95), " 74 | "permit VARCHAR(95), " 75 | "secret VARCHAR(80), " 76 | "md5secret VARCHAR(80), " 77 | "remotesecret VARCHAR(250), " 78 | "transport VARCHAR(10), " 79 | "host VARCHAR(31) default '' not null, " 80 | "nat VARCHAR(5) DEFAULT 'no' not null, " 81 | "type VARCHAR(10) DEFAULT 'friend' not null, " 82 | "accountcode VARCHAR(20), " 83 | "amaflags VARCHAR(13), " 84 | "callgroup VARCHAR(10), " 85 | "callerid VARCHAR(80), " 86 | "defaultip VARCHAR(40) DEFAULT '0.0.0.0', " 87 | "dtmfmode VARCHAR(7) DEFAULT 'info', " 88 | "fromuser VARCHAR(80), " 89 | "fromdomain VARCHAR(80), " 90 | "insecure VARCHAR(4), " 91 | "language CHAR(2), " 92 | "mailbox VARCHAR(50), " 93 | "pickupgroup VARCHAR(10), " 94 | "qualify CHAR(3), " 95 | "regexten VARCHAR(80), " 96 | "rtptimeout CHAR(3), " 97 | "rtpholdtimeout CHAR(3), " 98 | "setvar VARCHAR(100), " 99 | "disallow VARCHAR(100) DEFAULT 'all', " 100 | "allow VARCHAR(100) DEFAULT 'gsm' not null, " 101 | "fullcontact VARCHAR(80), " 102 | "ipaddr VARCHAR(45), " 103 | "port int(5) DEFAULT 5062, " 104 | "username VARCHAR(80), " 105 | "defaultuser VARCHAR(80), " 106 | "subscribecontext VARCHAR(80), " 107 | "directmedia VARCHAR(3), " 108 | "trustrpid VARCHAR(3), " 109 | "sendrpid VARCHAR(3), " 110 | "progressinband VARCHAR(5), " 111 | "promiscredir VARCHAR(3), " 112 | "useclientcode VARCHAR(3), " 113 | "callcounter VARCHAR(3), " 114 | "busylevel int(11) default 1, " 115 | "allowoverlap VARCHAR(3) DEFAULT 'no', " 116 | "allowsubscribe VARCHAR(3) DEFAULT 'no', " 117 | "allowtransfer VARCHAR(3) DEFAULT 'no', " 118 | "ignoresdpversion VARCHAR(3) DEFAULT 'no', " 119 | "template VARCHAR(100), " 120 | "videosupport VARCHAR(6) DEFAULT 'no', " 121 | "maxcallbitrate int(11), " 122 | "rfc2833compensate VARCHAR(3) DEFAULT 'yes', " 123 | "'session-timers' VARCHAR(10) DEFAULT 'accept', " 124 | "'session-expires' int(6) DEFAULT 1800, " 125 | "'session-minse' int(6) DEFAULT 90, " 126 | "'session-refresher' VARCHAR(3) DEFAULT 'uas', " 127 | "t38pt_usertpsource VARCHAR(3), " 128 | "outboundproxy VARCHAR(250), " 129 | "callbackextension VARCHAR(250), " 130 | "registertrying VARCHAR(3) DEFAULT 'yes', " 131 | "timert1 int(6) DEFAULT 500, " 132 | "timerb int(9), " 133 | "qualifyfreq int(6) DEFAULT 120, " 134 | "contactpermit VARCHAR(250), " 135 | "contactdeny VARCHAR(250), " 136 | "lastms int(11) DEFAULT 0 not null, " 137 | "regserver VARCHAR(100), " 138 | "regseconds int(11) DEFAULT 0 not null, " 139 | "useragent VARCHAR(100), " 140 | "cancallforward CHAR(3) DEFAULT 'yes' not null, " 141 | "canreinvite CHAR(3) DEFAULT 'no' not null, " 142 | "mask VARCHAR(95), " 143 | "musiconhold VARCHAR(100), " 144 | "restrictcid CHAR(3), " 145 | "calllimit int(5) default 1, " 146 | "WhiteListFlag timestamp not null default '0', " 147 | "WhiteListCode varchar(8) not null default '0', " 148 | "rand varchar(33) default '', " 149 | "sres varchar(33) default '', " 150 | "ki varchar(33) default '', " 151 | "kc varchar(33) default '', " 152 | "prepaid int(1) DEFAULT 0 not null, " // flag to indicate prepaid customer 153 | "account_balance int(9) default 0 not null, " // current account, neg is debt, pos is credit 154 | "RRLPSupported int(1) default 1 not null, " 155 | "hardware VARCHAR(20), " 156 | "regTime INTEGER default 0 NOT NULL, " // Unix time of most recent registration 157 | "a3_a8 varchar(45) default NULL" 158 | ")" 159 | }; 160 | 161 | static const char* createMEMSBTable = { 162 | "CREATE TABLE IF NOT EXISTS memcache.mem_sip_buddies (" 163 | "username varchar(80) primary key, " 164 | "ipaddr varchar(45), " 165 | "port int(5) default 5062, " 166 | "rand varchar(33) default '', " 167 | "sres varchar(33) default ''" 168 | ")" 169 | }; 170 | 171 | int SubscriberRegistry::init() 172 | { 173 | string ldb = gConfig.getStr("SubscriberRegistry.db"); 174 | size_t p = ldb.find_last_of('/'); 175 | if (p == string::npos) { 176 | LOG(EMERG) << "SubscriberRegistry.db not in a directory?"; 177 | mDB = NULL; 178 | return 1; 179 | } 180 | string dir = ldb.substr(0, p); 181 | struct stat buf; 182 | if (stat(dir.c_str(), &buf)) { 183 | LOG(EMERG) << dir << " does not exist"; 184 | mDB = NULL; 185 | return 1; 186 | } 187 | mNumSQLTries=gConfig.getNum("Control.NumSQLTries"); 188 | int rc = sqlite3_open(ldb.c_str(),&mDB); 189 | if (rc) { 190 | LOG(EMERG) << "Cannot open SubscriberRegistry database: " << ldb << " error: " << sqlite3_errmsg(mDB); 191 | sqlite3_close(mDB); 192 | mDB = NULL; 193 | return 1; 194 | } 195 | if (!sqlite3_command(mDB,createRRLPTable,mNumSQLTries)) { 196 | LOG(EMERG) << "Cannot create RRLP table"; 197 | return 1; 198 | } 199 | if (!sqlite3_command(mDB,createDDTable,mNumSQLTries)) { 200 | LOG(EMERG) << "Cannot create DIALDATA_TABLE table"; 201 | return 1; 202 | } 203 | if (!sqlite3_command(mDB,createRateTable,mNumSQLTries)) { 204 | LOG(EMERG) << "Cannot create rate table"; 205 | return 1; 206 | } 207 | if (!sqlite3_command(mDB,createSBTable,mNumSQLTries)) { 208 | LOG(EMERG) << "Cannot create SIP_BUDDIES table"; 209 | return 1; 210 | } 211 | // Set high-concurrency WAL mode. 212 | if (!sqlite3_command(mDB,enableWAL,mNumSQLTries)) { 213 | LOG(EMERG) << "Cannot enable WAL mode on database at " << ldb << ", error message: " << sqlite3_errmsg(mDB); 214 | } 215 | 216 | #ifndef SR_API_ONLY 217 | // memory based sip_buddies table 218 | if (!sqlite3_command(mDB,"attach database ':memory:' as memcache",mNumSQLTries)) { 219 | LOG(EMERG) << "Cannot create memcache database"; 220 | return 1; 221 | } 222 | if (!sqlite3_command(mDB,createMEMSBTable,mNumSQLTries)) { 223 | LOG(EMERG) << "Cannot create memcache mem_sip_buddies table"; 224 | return 1; 225 | } 226 | if (!sqlite3_command(mDB,"INSERT INTO mem_sip_buddies SELECT username, ipaddr, port, rand, sres FROM sip_buddies",mNumSQLTries)) { 227 | LOG(EMERG) << "Cannot populate mem_sip_buddies table with disk contents"; 228 | return 1; 229 | } 230 | if (!sqlite3_command(mDB,"ALTER TABLE mem_sip_buddies ADD dirty INTEGER DEFAULT 0",mNumSQLTries)) { 231 | LOG(EMERG) << "Cannot add dirty column to mem_sip_buddies table"; 232 | return 1; 233 | } 234 | 235 | // Start the sync thread 236 | mSyncer.start((void*(*)(void*))subscriberRegistrySyncer,NULL); 237 | #endif 238 | 239 | return 0; 240 | } 241 | 242 | string SubscriberRegistry::getResultsAsString(string query) 243 | { 244 | sqlite3_stmt *stmt; 245 | 246 | if (sqlite3_prepare_statement(mDB, &stmt, query.c_str(), 5)) { 247 | std::cout << " - sqlite3_prepare_statement() failed" << std::endl; 248 | return ""; 249 | } 250 | 251 | int state; 252 | int row = 0; 253 | int col; 254 | int colMax = sqlite3_column_count(stmt); 255 | const char* colName; 256 | const char* colText; 257 | ostringstream colNames; 258 | ostringstream colTexts; 259 | while (1) { 260 | state = sqlite3_step(stmt); 261 | if (state == SQLITE_ROW) { 262 | for (col = 0; col < colMax; col++) { 263 | colName = (const char*)sqlite3_column_name(stmt, col); 264 | colText = (const char*)sqlite3_column_text(stmt, col); 265 | 266 | if (row == 0) { 267 | colNames << colName << " "; 268 | } 269 | if (colText == NULL) { 270 | colTexts << "NULL" << " "; 271 | } else { 272 | colTexts << colText << " "; 273 | } 274 | } 275 | } else if (state == SQLITE_DONE) { 276 | break; 277 | // TODO : handle more SQLITE_FAILURECODES here 278 | } else { 279 | return " - failed in while(1) in } else {"; 280 | } 281 | colTexts << std::endl; 282 | row++; 283 | } 284 | sqlite3_finalize(stmt); 285 | 286 | ostringstream s; 287 | string title = colNames.str(); 288 | if (title.length()) { 289 | s << title << std::endl; 290 | s << colTexts << std::endl; 291 | } else { 292 | s << " - none found" << std::endl; 293 | } 294 | 295 | return s.str(); 296 | } 297 | 298 | vector SubscriberRegistry::getTableColumns(string tableName) 299 | { 300 | vector colNames; 301 | stringstream tmp; 302 | tmp << "select * from " << tableName << " limit 1"; 303 | 304 | sqlite3_stmt *stmt; 305 | 306 | if (sqlite3_prepare_statement(mDB, &stmt, tmp.str().c_str(), 5)) { 307 | std::cout << " - getTableColumns() - sqlite3_prepare_statement() failed" << std::endl; 308 | return colNames; 309 | } 310 | tmp.str(""); 311 | 312 | int state; 313 | int col; 314 | int colMax = sqlite3_column_count(stmt); 315 | while (1) { 316 | state = sqlite3_step(stmt); 317 | if (state == SQLITE_ROW) { 318 | for (col = 0; col < colMax; col++) { 319 | tmp << (const char*)sqlite3_column_name(stmt, col); 320 | colNames.push_back(tmp.str()); 321 | tmp.str(""); 322 | } 323 | } else if (state == SQLITE_DONE) { 324 | break; 325 | // TODO : handle more SQLITE_FAILURECODES here 326 | } else { 327 | std::cout << " - getTableColumns() - failed in while(1) in } else {" << std::endl; 328 | return colNames; 329 | } 330 | } 331 | sqlite3_finalize(stmt); 332 | 333 | return colNames; 334 | } 335 | 336 | #ifndef SR_API_ONLY 337 | string SubscriberRegistry::generateSyncToDiskQuery() 338 | { 339 | vector columns = getTableColumns("sip_buddies"); 340 | if (!columns.size()) { 341 | LOG(DEBUG) << "sip_buddies is empty"; 342 | return ""; 343 | } 344 | 345 | sort(columns.begin(), columns.end()); 346 | std::stringstream ss; 347 | unsigned i; 348 | 349 | ss << "replace into sip_buddies (ipaddr, port, rand, sres, "; 350 | 351 | for (i = 0; i < columns.size(); i++) { 352 | if (columns[i].compare("ipaddr") == 0 || columns[i].compare("port") == 0 || 353 | columns[i].compare("rand") == 0 || columns[i].compare("sres") == 0) { 354 | continue; 355 | } 356 | if (i != 0) { 357 | ss << ", "; 358 | } 359 | 360 | if (columns[i].find("-") != std::string::npos) { 361 | ss << "'" << columns[i] << "'"; 362 | } else { 363 | ss << columns[i]; 364 | } 365 | } 366 | 367 | ss << ") select src.ipaddr, src.port, src.rand, src.sres, "; 368 | 369 | for (i = 0; i < columns.size(); i++) { 370 | if (columns[i].compare("ipaddr") == 0 || columns[i].compare("port") == 0 || 371 | columns[i].compare("rand") == 0 || columns[i].compare("sres") == 0) { 372 | continue; 373 | } 374 | if (i != 0) { 375 | ss << ", "; 376 | } 377 | 378 | ss << "dest."; 379 | if (columns[i].find("-") != std::string::npos) { 380 | ss << "'" << columns[i] << "'"; 381 | } else { 382 | ss << columns[i]; 383 | } 384 | } 385 | 386 | ss << " from mem_sip_buddies src "; 387 | ss << "inner join sip_buddies dest on src.username = dest.username "; 388 | ss << "where src.dirty = \"1\""; 389 | 390 | return ss.str(); 391 | } 392 | 393 | bool SubscriberRegistry::syncMemoryDB() 394 | { 395 | bool ret = true; 396 | string syncToDisk = generateSyncToDiskQuery(); 397 | 398 | string cleanDirty = "update mem_sip_buddies set dirty = \"0\""; 399 | 400 | string syncFromDiskAddNewEntries = "INSERT INTO mem_sip_buddies " 401 | "(username, ipaddr, port, rand, sres, dirty) " 402 | "SELECT sip_buddies.username, sip_buddies.ipaddr, sip_buddies.port, sip_buddies.rand, sip_buddies.sres, '0' FROM sip_buddies " 403 | "LEFT OUTER JOIN mem_sip_buddies ON (mem_sip_buddies.username=sip_buddies.username) " 404 | "WHERE mem_sip_buddies.username IS NULL"; 405 | 406 | string syncFromDiskDeleteOldEntries = "DELETE FROM mem_sip_buddies " 407 | "WHERE username IN " 408 | "(SELECT mem_sip_buddies.username FROM mem_sip_buddies" 409 | " LEFT JOIN sip_buddies ON mem_sip_buddies.username=sip_buddies.username" 410 | " WHERE sip_buddies.username IS NULL" 411 | ")"; 412 | 413 | Timeval timer; 414 | mLock.lock(); 415 | 416 | // this string is only non-empty if there are entries in sip_buddies 417 | if (syncToDisk.length()) { 418 | // sync dirty entries to disk 419 | if (sqlUpdate(syncToDisk.c_str()) == FAILURE) { 420 | LOG(ERR) << "syncToDisk failed"; 421 | } else { 422 | // if it succeeds, mark these entries as clean again 423 | LOG(INFO) << "syncToDisk succeeded"; 424 | if (sqlUpdate(cleanDirty.c_str()) == FAILURE) { 425 | LOG(ERR) << "cleanDirty failed"; 426 | } else { 427 | LOG(INFO) << "cleanDirty succeeded"; 428 | } 429 | } 430 | 431 | // sync new rows from the disk into memory 432 | if (sqlUpdate(syncFromDiskAddNewEntries.c_str()) == FAILURE) { 433 | LOG(ERR) << "syncFromDiskAddNewEntries failed"; 434 | } else { 435 | LOG(INFO) << "syncFromDiskAddNewEntries succeeded"; 436 | } 437 | } 438 | 439 | // delete old entries from memory no longer found on the disk 440 | if (sqlUpdate(syncFromDiskDeleteOldEntries.c_str()) == FAILURE) { 441 | LOG(ERR) << "syncFromDiskDeleteOldEntries failed"; 442 | } else { 443 | LOG(INFO) << "syncFromDiskDeleteOldEntries succeeded"; 444 | } 445 | 446 | mLock.unlock(); 447 | LOG(INFO) << "syncMemoryDB() locked the db for " << timer.elapsed() << "ms"; 448 | 449 | return ret; 450 | } 451 | #endif 452 | 453 | SubscriberRegistry::~SubscriberRegistry() 454 | { 455 | if (mDB) sqlite3_close(mDB); 456 | } 457 | 458 | 459 | 460 | SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr) 461 | { 462 | LOG(INFO) << query; 463 | 464 | if (!resultptr) { 465 | if (!sqlite3_command(db(), query, mNumSQLTries)) return FAILURE; 466 | return SUCCESS; 467 | } 468 | 469 | sqlite3_stmt *stmt; 470 | if (sqlite3_prepare_statement(db(), &stmt, query, mNumSQLTries)) { 471 | LOG(ERR) << "sqlite3_prepare_statement problem with query \"" << query << "\""; 472 | return FAILURE; 473 | } 474 | int src = sqlite3_run_query(db(), stmt, mNumSQLTries); 475 | if (src != SQLITE_ROW) { 476 | sqlite3_finalize(stmt); 477 | return FAILURE; 478 | } 479 | char *column = (char*)sqlite3_column_text(stmt, 0); 480 | if (!column) { 481 | LOG(ERR) << "Subscriber registry returned a NULL column."; 482 | sqlite3_finalize(stmt); 483 | return FAILURE; 484 | } 485 | *resultptr = strdup(column); 486 | sqlite3_finalize(stmt); 487 | return SUCCESS; 488 | } 489 | 490 | 491 | char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue) 492 | { 493 | char *result = NULL; 494 | SubscriberRegistry::Status st; 495 | ostringstream os; 496 | os << "select " << unknownColumn << " from " << table << " where " << knownColumn << " = \"" << knownValue << "\""; 497 | // try to find locally 498 | st = sqlLocal(os.str().c_str(), &result); 499 | if ((st == SUCCESS) && result) { 500 | // got it. return it. 501 | LOG(INFO) << "result = " << result; 502 | return result; 503 | } 504 | // didn't find locally 505 | LOG(INFO) << "not found: " << os.str(); 506 | return NULL; 507 | } 508 | 509 | 510 | /* 511 | * Check for two of the same values for a single unknown 512 | */ 513 | char *SubscriberRegistry::sqlQuery2(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue1, const char *knownValue2) 514 | { 515 | char *result = NULL; 516 | SubscriberRegistry::Status st; 517 | ostringstream os; 518 | // select knownValue from table where knownColumn IN ('knownValue1', 'knownValue2') 519 | os << "select " << unknownColumn << " from " << table << " where " << knownColumn << " IN (\'" 520 | << knownValue1 << "\', " << "\'" << knownValue2 << "\')"; 521 | //LOG(INFO) << "QUERY STRING = " << os.str().c_str(); 522 | 523 | // try to find locally 524 | st = sqlLocal(os.str().c_str(), &result); 525 | if ((st == SUCCESS) && result) { 526 | // got it. return it. 527 | LOG(INFO) << "result = " << result; 528 | return result; 529 | } 530 | // didn't find locally 531 | LOG(INFO) << "not found: " << os.str(); 532 | return NULL; 533 | } 534 | 535 | 536 | SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt) 537 | { 538 | LOG(INFO) << stmt; 539 | return sqlLocal(stmt, NULL); 540 | } 541 | 542 | string SubscriberRegistry::imsiGet(string imsi, string key) 543 | { 544 | string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; 545 | char *st = sqlQuery(key.c_str(), "sip_buddies", "username", name.c_str()); 546 | if (!st) { 547 | LOG(INFO) << "cannot get key " << key << " for username " << name; 548 | return ""; 549 | } 550 | return st; 551 | } 552 | 553 | #ifndef SR_API_ONLY 554 | bool SubscriberRegistry::imsiSet(string imsi, string key, string value) 555 | { 556 | string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; 557 | ostringstream os; 558 | os << "update mem_sip_buddies set dirty = \"1\", " << key << " = \"" << value << "\" where username = \"" << name << "\""; 559 | 560 | mLock.lock(); 561 | SubscriberRegistry::Status ret = sqlUpdate(os.str().c_str()); 562 | mLock.unlock(); 563 | 564 | return ret == FAILURE; 565 | } 566 | 567 | bool SubscriberRegistry::imsiSet(string imsi, string key1, string value1, string key2, string value2) 568 | { 569 | string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi; 570 | ostringstream os; 571 | os << "update mem_sip_buddies set dirty = \"1\", " << key1 << " = \"" << value1 << "\"," << key2 << " = \"" << value2 << "\" where username = \"" << name << "\""; 572 | 573 | mLock.lock(); 574 | SubscriberRegistry::Status ret = sqlUpdate(os.str().c_str()); 575 | mLock.unlock(); 576 | 577 | return ret == FAILURE; 578 | } 579 | #endif 580 | 581 | /* 582 | * Get IMSI from phone number 583 | * Should be able to get rid of this one 584 | */ 585 | char *SubscriberRegistry::getIMSI(const char *ISDN) 586 | { 587 | if (!ISDN) { 588 | LOG(WARNING) << "SubscriberRegistry::getIMSI attempting lookup of NULL ISDN"; 589 | return NULL; 590 | } 591 | LOG(INFO) << "getIMSI(" << ISDN << ")"; 592 | return sqlQuery("dial", "dialdata_table", "exten", ISDN); 593 | } 594 | 595 | 596 | /* 597 | * This version handle phone number with or without a plus at the beginning 598 | * This should work for all uses of getIMSI 599 | * 600 | */ 601 | char *SubscriberRegistry::getIMSI2(const char *ISDN) 602 | { 603 | if (!ISDN) { 604 | LOG(WARNING) << "SubscriberRegistry::getIMSI2 attempting lookup of NULL ISDN"; 605 | return NULL; 606 | } 607 | LOG(INFO) << "getIMSI2(" << ISDN << ")"; 608 | char* str2; 609 | char localstr[50]; 610 | if (ISDN[0] == '+') { 611 | str2 = (char *) &ISDN[1]; // ISDN has plus remove plus for str2 612 | } else { 613 | // ISDN no plus add plus to str2 614 | strcpy(&localstr[0], "+"); 615 | strncat(localstr, ISDN, sizeof(localstr)-1); 616 | localstr[sizeof(localstr)-1] = 0; 617 | str2 = localstr; 618 | } 619 | // Two strings one with plus one without 620 | return sqlQuery2("dial", "dialdata_table", "exten", ISDN, (const char*) str2); 621 | } 622 | 623 | 624 | char *SubscriberRegistry::getCLIDLocal(const char* IMSI) 625 | { 626 | if (!IMSI) { 627 | LOG(WARNING) << "SubscriberRegistry::getCLIDLocal attempting lookup of NULL IMSI"; 628 | return NULL; 629 | } 630 | LOG(INFO) << "getCLIDLocal(" << IMSI << ")"; 631 | return sqlQuery("callerid", "sip_buddies", "username", IMSI); 632 | } 633 | 634 | 635 | 636 | char *SubscriberRegistry::getCLIDGlobal(const char* IMSI) 637 | { 638 | if (!IMSI) { 639 | LOG(WARNING) << "SubscriberRegistry::getCLIDGlobal attempting lookup of NULL IMSI"; 640 | return NULL; 641 | } 642 | LOG(INFO) << "getCLIDGlobal(" << IMSI << ")"; 643 | return sqlQuery("callerid", "sip_buddies", "username", IMSI); 644 | } 645 | 646 | 647 | 648 | char *SubscriberRegistry::getRegistrationIP(const char* IMSI) 649 | { 650 | if (!IMSI) { 651 | LOG(WARNING) << "SubscriberRegistry::getRegistrationIP attempting lookup of NULL IMSI"; 652 | return NULL; 653 | } 654 | LOG(INFO) << "getRegistrationIP(" << IMSI << ")"; 655 | return sqlQuery("ipaddr", "sip_buddies", "username", IMSI); 656 | } 657 | 658 | 659 | 660 | SubscriberRegistry::Status SubscriberRegistry::setRegTime(const char* IMSI) 661 | { 662 | if (!IMSI) { 663 | LOG(WARNING) << "SubscriberRegistry::setRegTime attempting set for NULL IMSI"; 664 | return FAILURE; 665 | } 666 | unsigned now = (unsigned)time(NULL); 667 | ostringstream os; 668 | os << "update sip_buddies set regTime = " << now << " where username = " << '"' << IMSI << '"'; 669 | return sqlUpdate(os.str().c_str()); 670 | } 671 | 672 | 673 | 674 | SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const char* CLID) 675 | { 676 | if (!IMSI) { 677 | LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI"; 678 | return FAILURE; 679 | } 680 | if (!CLID) { 681 | LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL CLID"; 682 | return FAILURE; 683 | } 684 | LOG(INFO) << "addUser(" << IMSI << "," << CLID << ")"; 685 | ostringstream os; 686 | os << "insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode, ipaddr, port) values ("; 687 | os << "\"" << IMSI << "\""; 688 | os << ","; 689 | os << "\"" << IMSI << "\""; 690 | os << ","; 691 | os << "\"" << "friend" << "\""; 692 | os << ","; 693 | os << "\"" << "phones" << "\""; 694 | os << ","; 695 | os << "\"" << "dynamic" << "\""; 696 | os << ","; 697 | os << "\"" << CLID << "\""; 698 | os << ","; 699 | os << "\"" << "no" << "\""; 700 | os << ","; 701 | os << "\"" << "gsm" << "\""; 702 | os << ","; 703 | os << "\"" << "info" << "\""; 704 | os << ","; 705 | os << "\"" << "127.0.0.1" << "\""; 706 | os << ","; 707 | os << "\"" << "5062" << "\""; 708 | os << ")"; 709 | os << ";"; 710 | SubscriberRegistry::Status st = sqlUpdate(os.str().c_str()); 711 | ostringstream os2; 712 | os2 << "insert into dialdata_table (exten, dial) values ("; 713 | os2 << "\"" << CLID << "\""; 714 | os2 << ","; 715 | os2 << "\"" << IMSI << "\""; 716 | os2 << ")"; 717 | SubscriberRegistry::Status st2 = sqlUpdate(os2.str().c_str()); 718 | return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE; 719 | } 720 | 721 | 722 | char *SubscriberRegistry::mapCLIDGlobal(const char *local) 723 | { 724 | if (!local) { 725 | LOG(WARNING) << "SubscriberRegistry::mapCLIDGlobal attempting lookup of NULL local"; 726 | return NULL; 727 | } 728 | LOG(INFO) << "mapCLIDGlobal(" << local << ")"; 729 | char *IMSI = getIMSI2(local); 730 | if (!IMSI) return NULL; 731 | char *global = getCLIDGlobal(IMSI); 732 | free(IMSI); 733 | return global; 734 | } 735 | 736 | SubscriberRegistry::Status SubscriberRegistry::RRLPUpdate(string name, string lat, string lon, string err){ 737 | ostringstream os; 738 | os << "insert into RRLP (name, latitude, longitude, error, time) values (" << 739 | '"' << name << '"' << "," << 740 | lat << "," << 741 | lon << "," << 742 | err << "," << 743 | "datetime('now')" 744 | ")"; 745 | LOG(INFO) << os.str(); 746 | return sqlUpdate(os.str().c_str()); 747 | } 748 | 749 | #ifndef SR_API_ONLY 750 | extern SubscriberRegistry gSubscriberRegistry; 751 | void* subscriberRegistrySyncer(void*) 752 | { 753 | while (true) { 754 | sleep(15); 755 | gSubscriberRegistry.syncMemoryDB(); 756 | } 757 | 758 | return NULL; 759 | } 760 | #endif 761 | 762 | // vim: ts=4 sw=4 763 | -------------------------------------------------------------------------------- /SubscriberRegistry.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Kestrel Signal Processing, Inc. 3 | * Copyright 2011, 2012, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under the terms of the GNU Affero Public License. 6 | * See the COPYING file in the main directory for details. 7 | * 8 | * This use of this software may be subject to additional restrictions. 9 | * See the LEGAL file in the main directory for details. 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU Affero General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Affero General Public License for more details. 20 | 21 | You should have received a copy of the GNU Affero General Public License 22 | along with this program. If not, see . 23 | 24 | */ 25 | 26 | #ifndef SubscriberRegistry_H 27 | #define SubscriberRegistry_H 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "sqlite3.h" 37 | 38 | using namespace std; 39 | 40 | class SubscriberRegistry { 41 | 42 | private: 43 | 44 | sqlite3 *mDB; ///< database connection 45 | unsigned mNumSQLTries; ///< Number of times to try an sqlite command before giving up. 46 | 47 | #ifndef SR_API_ONLY 48 | mutable Mutex mLock; ///< control for multithreaded read/write access to the memory based sip_buddies table 49 | Thread mSyncer; ///< thread responsible for synchronizing the memory and disk based sip_buddies tables 50 | #endif 51 | 52 | public: 53 | 54 | ~SubscriberRegistry(); 55 | 56 | /** 57 | Initialize the subscriber registry using parameters from gConfig. 58 | @return 0 if the database was successfully opened and initialized; 1 otherwise 59 | */ 60 | int init(); 61 | 62 | typedef enum { 63 | SUCCESS=0, ///< operation successful 64 | FAILURE=1, ///< operation not successful 65 | DELAYED=2, ///< operation successful, but effect delayed 66 | TRYAGAIN=3 ///< operation not attempted, try again later 67 | } Status; 68 | 69 | 70 | sqlite3 *db() 71 | { 72 | return mDB; 73 | } 74 | 75 | 76 | /** 77 | Grab the memory based sqlite db as a table string 78 | */ 79 | string getResultsAsString(string query); 80 | 81 | /** 82 | Grab the columns from a table 83 | */ 84 | vector getTableColumns(string tableName); 85 | 86 | #ifndef SR_API_ONLY 87 | /** 88 | Generate the SQL query which is used to sync the in-memory database to disk 89 | to account for differences in database schemas. 90 | */ 91 | string generateSyncToDiskQuery(); 92 | 93 | /** 94 | Sync the in-memory sip_buddies table to disk. 95 | */ 96 | bool syncMemoryDB(); 97 | #endif 98 | 99 | /** 100 | Resolve an ISDN or other numeric address to an IMSI. 101 | @param ISDN Any numeric address, E.164, local extension, etc. 102 | @return A C-string to be freed by the caller, 103 | NULL if the ISDN cannot be resolved. 104 | */ 105 | char* getIMSI(const char* ISDN); 106 | char* getIMSI2(const char *ISDN); // This version works with a plus 107 | 108 | /** 109 | Given an IMSI, return the local CLID, which should be a numeric address. 110 | @param IMSI The subscriber IMSI. 111 | @return A C-string to be freed by the caller, 112 | NULL if the IMSI isn't found. 113 | */ 114 | char* getCLIDLocal(const char* IMSI); 115 | 116 | /** 117 | Given an IMSI, return the global CLID, which should be a numeric address. 118 | @param IMSI The subscriber IMSI. 119 | @return A C-string to be freed by the caller, 120 | NULL if the IMSI isn't found. 121 | */ 122 | char* getCLIDGlobal(const char* IMSI); 123 | 124 | /** 125 | Given an IMSI, return the IP address of the most recent registration. 126 | @param IMSI The subscriber IMSI 127 | @return A C-string to be freed by the caller, "111.222.333.444:port", 128 | NULL if the ISMI isn't registered. 129 | */ 130 | char* getRegistrationIP(const char* IMSI); 131 | 132 | /** 133 | Get a subscriber's property. 134 | @param imsi imsi of the subscriber 135 | @param key name of the property 136 | */ 137 | string imsiGet(string imsi, string key); 138 | 139 | #ifndef SR_API_ONLY 140 | /** 141 | Set a subscriber's property. 142 | @param imsi imsi of the subscriber 143 | @param key name of the property 144 | @param value value of the property 145 | */ 146 | bool imsiSet(string imsi, string key, string value); 147 | 148 | /** 149 | Set a subscriber's property. 150 | @param imsi imsi of the subscriber 151 | @param key1 name of the property 152 | @param value1 value of the property 153 | @param key2 name of the property 154 | @param value2 value of the property 155 | */ 156 | bool imsiSet(string imsi, string key1, string value1, string key2, string value2); 157 | #endif 158 | 159 | /** 160 | Add a new user to the SubscriberRegistry. 161 | @param IMSI The user's IMSI or SIP username. 162 | @param CLID The user's local CLID. 163 | */ 164 | Status addUser(const char* IMSI, const char* CLID); 165 | 166 | 167 | /** 168 | Remove a user from the SubscriberRegistry. 169 | @param IMSI The user's IMSI or SIP username. 170 | */ 171 | Status removeUser(const char* IMSI); 172 | 173 | 174 | /** 175 | Set the current time as the time of the most recent registration for an IMSI. 176 | @param IMSI The user's IMSI or SIP username. 177 | */ 178 | Status setRegTime(const char* IMSI); 179 | 180 | 181 | char *mapCLIDGlobal(const char *local); 182 | 183 | 184 | /** 185 | Update the RRLP location for user 186 | @param name IMSI to be updated 187 | @param lat Latitude 188 | @param lon Longitude 189 | @param err Approximate Error 190 | */ 191 | Status RRLPUpdate(string name, string lat, string lon, string err); 192 | 193 | 194 | private: 195 | 196 | 197 | 198 | /** 199 | Run sql statments locally. 200 | @param stmt The sql statements. 201 | @param resultptr Set this to point to the result of executing the statements. 202 | */ 203 | Status sqlLocal(const char *stmt, char **resultptr); 204 | 205 | 206 | 207 | /** 208 | Run an sql query (select unknownColumn from table where knownColumn = knownValue). 209 | @param unknownColumn The column whose value you want. 210 | @param table The table to look in. 211 | @param knownColumn The column with the value you know. 212 | @param knownValue The known value of knownColumn. 213 | */ 214 | char *sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue); 215 | 216 | 217 | /** 218 | Run an sql query (select unknownColumn from table where knownColumn = knownValue). 219 | @param unknownColumn The column whose value you want. 220 | @param table The table to look in. 221 | @param knownColumn The column with the value you know. 222 | @param knownValue1 The first known value of knownColumn. 223 | @param knownValue2 The second known value of knownColumn. 224 | */ 225 | char *sqlQuery2(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue1, const char *knownValue2); 226 | 227 | 228 | /** 229 | Run an sql update. 230 | @param stmt The update statement. 231 | */ 232 | Status sqlUpdate(const char *stmt); 233 | 234 | 235 | }; 236 | 237 | /** Periodically triggers SubscriberRegistry::syncMemoryDB(). */ 238 | void* subscriberRegistrySyncer(void*); 239 | 240 | 241 | #endif 242 | 243 | // vim: ts=4 sw=4 244 | -------------------------------------------------------------------------------- /apps/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2013, 2014 Range Networks, Inc. 3 | # 4 | # This software is distributed under the terms of the GNU Public License. 5 | # See the COPYING file in the main directory for details. 6 | # 7 | # This program is free software: you can redistribute it and/or modify 8 | # it under the terms of the GNU General Public License as published by 9 | # the Free Software Foundation, either version 3 of the License, or 10 | # (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program. If not, see . 19 | # 20 | 21 | include $(top_srcdir)/Makefile.common 22 | 23 | DESTDIR := 24 | 25 | ourlibs = \ 26 | $(GLOBALS_LA) \ 27 | $(COMMON_LA) \ 28 | $(NODEMANAGER_LA) 29 | 30 | sbin_PROGRAMS = sipauthserve comp128 31 | bin_SCRIPTS = syslogextractor hexmapper 32 | confdir = /etc/OpenBTS 33 | conf_DATA = sipauthserve.example.sql 34 | 35 | sipauthserve_SOURCES = sipauthserve.cpp \ 36 | ../servershare.cpp \ 37 | ../SubscriberRegistry.cpp \ 38 | ../NodeManager/JSONDB/JSONDB.cpp 39 | sipauthserve_LDADD = $(ourlibs) -losipparser2 -losip2 40 | 41 | comp128_SOURCES = comp128.c 42 | comp128_LDADD = $(ourlibs) 43 | 44 | sipauthserve.example.sql: sipauthserve 45 | ( ./sipauthserve --gensql > sipauthserve.example.sql || true ) 46 | 47 | tmp_DB = /tmp/SR.db 48 | TESTS = checkdb.sh 49 | CLEANFILES = $(tmp_DB) 50 | 51 | -------------------------------------------------------------------------------- /apps/checkdb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | tmp_DB='/tmp/SR.db' 6 | conf_DATA='./sipauthserve.example.sql' 7 | 8 | if [ ! -f ${conf_DATA} ]; then 9 | exit 1 10 | fi 11 | 12 | echo "* check integrity of ${conf_DATA}" 13 | sqlite3 -bail ${tmp_DB} ".read ${conf_DATA}" > /dev/null 14 | exit $? 15 | -------------------------------------------------------------------------------- /apps/comp128.c: -------------------------------------------------------------------------------- 1 | /* An implementation of the GSM A3A8 algorithm. (Specifically, COMP128.) 2 | */ 3 | 4 | /* Copyright 1998, Marc Briceno, Ian Goldberg, and David Wagner. 5 | * All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions are met: 9 | * 10 | * * Redistributions of source code must retain the above copyright notice, 11 | * this list of conditions and the following disclaimer. 12 | * 13 | * * Redistributions in binary form must reproduce the above copyright notice, 14 | * this list of conditions and the following disclaimer in the documentation 15 | * and/or other materials provided with the distribution. 16 | * 17 | * * Neither the name of the authors nor the names of the contributors 18 | * may be used to endorse or promote products derived from this software 19 | * without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | * POSSIBILITY OF SUCH DAMAGE. 32 | */ 33 | 34 | /* 35 | * Coded in C merely because C is a much more precise, concise form of 36 | * expression for these purposes. See Judge Patel if you have any problems 37 | * with this... 38 | * Of course, it's only authentication, so it should be exportable for the 39 | * usual boring reasons. 40 | */ 41 | 42 | typedef unsigned char Byte; 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | /* #define TEST */ 50 | 51 | /* 52 | * rand[0..15]: the challenge from the base station 53 | * key[0..15]: the SIM's A3/A8 long-term key Ki 54 | * simoutput[0..11]: what you'd get back if you fed rand and key to a real 55 | * SIM. 56 | * 57 | * The GSM spec states that simoutput[0..3] is SRES, 58 | * and simoutput[4..11] is Kc (the A5 session key). 59 | * (See GSM 11.11, Section 8.16. See also the leaked document 60 | * referenced below.) 61 | * Note that Kc is bits 74..127 of the COMP128 output, followed by 10 62 | * zeros. 63 | * In other words, A5 is keyed with only 54 bits of entropy. This 64 | * represents a deliberate weakening of the key used for voice privacy 65 | * by a factor of over 1000. 66 | * 67 | * Verified with a Pacific Bell Schlumberger SIM. Your mileage may vary. 68 | * 69 | * Marc Briceno , Ian Goldberg , 70 | * and David Wagner 71 | */ 72 | 73 | void A3A8(/* in */ Byte rand[16], /* in */ Byte key[16], 74 | /* out */ Byte simoutput[12]); 75 | 76 | /* The compression tables. */ 77 | static const Byte table_0[512] = { 78 | 102,177,186,162, 2,156,112, 75, 55, 25, 8, 12,251,193,246,188, 79 | 109,213,151, 53, 42, 79,191,115,233,242,164,223,209,148,108,161, 80 | 252, 37,244, 47, 64,211, 6,237,185,160,139,113, 76,138, 59, 70, 81 | 67, 26, 13,157, 63,179,221, 30,214, 36,166, 69,152,124,207,116, 82 | 247,194, 41, 84, 71, 1, 49, 14, 95, 35,169, 21, 96, 78,215,225, 83 | 182,243, 28, 92,201,118, 4, 74,248,128, 17, 11,146,132,245, 48, 84 | 149, 90,120, 39, 87,230,106,232,175, 19,126,190,202,141,137,176, 85 | 250, 27,101, 40,219,227, 58, 20, 51,178, 98,216,140, 22, 32,121, 86 | 61,103,203, 72, 29,110, 85,212,180,204,150,183, 15, 66,172,196, 87 | 56,197,158, 0,100, 45,153, 7,144,222,163,167, 60,135,210,231, 88 | 174,165, 38,249,224, 34,220,229,217,208,241, 68,206,189,125,255, 89 | 239, 54,168, 89,123,122, 73,145,117,234,143, 99,129,200,192, 82, 90 | 104,170,136,235, 93, 81,205,173,236, 94,105, 52, 46,228,198, 5, 91 | 57,254, 97,155,142,133,199,171,187, 50, 65,181,127,107,147,226, 92 | 184,218,131, 33, 77, 86, 31, 44, 88, 62,238, 18, 24, 43,154, 23, 93 | 80,159,134,111, 9,114, 3, 91, 16,130, 83, 10,195,240,253,119, 94 | 177,102,162,186,156, 2, 75,112, 25, 55, 12, 8,193,251,188,246, 95 | 213,109, 53,151, 79, 42,115,191,242,233,223,164,148,209,161,108, 96 | 37,252, 47,244,211, 64,237, 6,160,185,113,139,138, 76, 70, 59, 97 | 26, 67,157, 13,179, 63, 30,221, 36,214, 69,166,124,152,116,207, 98 | 194,247, 84, 41, 1, 71, 14, 49, 35, 95, 21,169, 78, 96,225,215, 99 | 243,182, 92, 28,118,201, 74, 4,128,248, 11, 17,132,146, 48,245, 100 | 90,149, 39,120,230, 87,232,106, 19,175,190,126,141,202,176,137, 101 | 27,250, 40,101,227,219, 20, 58,178, 51,216, 98, 22,140,121, 32, 102 | 103, 61, 72,203,110, 29,212, 85,204,180,183,150, 66, 15,196,172, 103 | 197, 56, 0,158, 45,100, 7,153,222,144,167,163,135, 60,231,210, 104 | 165,174,249, 38, 34,224,229,220,208,217, 68,241,189,206,255,125, 105 | 54,239, 89,168,122,123,145, 73,234,117, 99,143,200,129, 82,192, 106 | 170,104,235,136, 81, 93,173,205, 94,236, 52,105,228, 46, 5,198, 107 | 254, 57,155, 97,133,142,171,199, 50,187,181, 65,107,127,226,147, 108 | 218,184, 33,131, 86, 77, 44, 31, 62, 88, 18,238, 43, 24, 23,154, 109 | 159, 80,111,134,114, 9, 91, 3,130, 16, 10, 83,240,195,119,253 110 | }, table_1[256] = { 111 | 19, 11, 80,114, 43, 1, 69, 94, 39, 18,127,117, 97, 3, 85, 43, 112 | 27,124, 70, 83, 47, 71, 63, 10, 47, 89, 79, 4, 14, 59, 11, 5, 113 | 35,107,103, 68, 21, 86, 36, 91, 85,126, 32, 50,109, 94,120, 6, 114 | 53, 79, 28, 45, 99, 95, 41, 34, 88, 68, 93, 55,110,125,105, 20, 115 | 90, 80, 76, 96, 23, 60, 89, 64,121, 56, 14, 74,101, 8, 19, 78, 116 | 76, 66,104, 46,111, 50, 32, 3, 39, 0, 58, 25, 92, 22, 18, 51, 117 | 57, 65,119,116, 22,109, 7, 86, 59, 93, 62,110, 78, 99, 77, 67, 118 | 12,113, 87, 98,102, 5, 88, 33, 38, 56, 23, 8, 75, 45, 13, 75, 119 | 95, 63, 28, 49,123,120, 20,112, 44, 30, 15, 98,106, 2,103, 29, 120 | 82,107, 42,124, 24, 30, 41, 16,108,100,117, 40, 73, 40, 7,114, 121 | 82,115, 36,112, 12,102,100, 84, 92, 48, 72, 97, 9, 54, 55, 74, 122 | 113,123, 17, 26, 53, 58, 4, 9, 69,122, 21,118, 42, 60, 27, 73, 123 | 118,125, 34, 15, 65,115, 84, 64, 62, 81, 70, 1, 24,111,121, 83, 124 | 104, 81, 49,127, 48,105, 31, 10, 6, 91, 87, 37, 16, 54,116,126, 125 | 31, 38, 13, 0, 72,106, 77, 61, 26, 67, 46, 29, 96, 37, 61, 52, 126 | 101, 17, 44,108, 71, 52, 66, 57, 33, 51, 25, 90, 2,119,122, 35 127 | }, table_2[128] = { 128 | 52, 50, 44, 6, 21, 49, 41, 59, 39, 51, 25, 32, 51, 47, 52, 43, 129 | 37, 4, 40, 34, 61, 12, 28, 4, 58, 23, 8, 15, 12, 22, 9, 18, 130 | 55, 10, 33, 35, 50, 1, 43, 3, 57, 13, 62, 14, 7, 42, 44, 59, 131 | 62, 57, 27, 6, 8, 31, 26, 54, 41, 22, 45, 20, 39, 3, 16, 56, 132 | 48, 2, 21, 28, 36, 42, 60, 33, 34, 18, 0, 11, 24, 10, 17, 61, 133 | 29, 14, 45, 26, 55, 46, 11, 17, 54, 46, 9, 24, 30, 60, 32, 0, 134 | 20, 38, 2, 30, 58, 35, 1, 16, 56, 40, 23, 48, 13, 19, 19, 27, 135 | 31, 53, 47, 38, 63, 15, 49, 5, 37, 53, 25, 36, 63, 29, 5, 7 136 | }, table_3[64] = { 137 | 1, 5, 29, 6, 25, 1, 18, 23, 17, 19, 0, 9, 24, 25, 6, 31, 138 | 28, 20, 24, 30, 4, 27, 3, 13, 15, 16, 14, 18, 4, 3, 8, 9, 139 | 20, 0, 12, 26, 21, 8, 28, 2, 29, 2, 15, 7, 11, 22, 14, 10, 140 | 17, 21, 12, 30, 26, 27, 16, 31, 11, 7, 13, 23, 10, 5, 22, 19 141 | }, table_4[32] = { 142 | 15, 12, 10, 4, 1, 14, 11, 7, 5, 0, 14, 7, 1, 2, 13, 8, 143 | 10, 3, 4, 9, 6, 0, 3, 2, 5, 6, 8, 9, 11, 13, 15, 12 144 | }, *table[5] = { table_0, table_1, table_2, table_3, table_4 }; 145 | 146 | /* 147 | * This code derived from a leaked document from the GSM standards. 148 | * Some missing pieces were filled in by reverse-engineering a working SIM. 149 | * We have verified that this is the correct COMP128 algorithm. 150 | * 151 | * The first page of the document identifies it as 152 | * _Technical Information: GSM System Security Study_. 153 | * 10-1617-01, 10th June 1988. 154 | * The bottom of the title page is marked 155 | * Racal Research Ltd. 156 | * Worton Drive, Worton Grange Industrial Estate, 157 | * Reading, Berks. RG2 0SB, England. 158 | * Telephone: Reading (0734) 868601 Telex: 847152 159 | * The relevant bits are in Part I, Section 20 (pages 66--67). Enjoy! 160 | * 161 | * Note: There are three typos in the spec (discovered by 162 | * reverse-engineering). 163 | * First, "z = (2 * x[n] + x[n]) mod 2^(9-j)" should clearly read 164 | * "z = (2 * x[m] + x[n]) mod 2^(9-j)". 165 | * Second, the "k" loop in the "Form bits from bytes" section is severely 166 | * botched: the k index should run only from 0 to 3, and clearly the range 167 | * on "the (8-k)th bit of byte j" is also off (should be 0..7, not 1..8, 168 | * to be consistent with the subsequent section). 169 | * Third, SRES is taken from the first 8 nibbles of x[], not the last 8 as 170 | * claimed in the document. (And the document doesn't specify how Kc is 171 | * derived, but that was also easily discovered with reverse engineering.) 172 | * All of these typos have been corrected in the following code. 173 | */ 174 | 175 | void A3A8(/* in */ Byte rand[16], /* in */ Byte key[16], 176 | /* out */ Byte simoutput[12]) 177 | { 178 | Byte x[32], bit[128]; 179 | int i, j, k, l, m, n, y, z, next_bit; 180 | 181 | /* ( Load RAND into last 16 bytes of input ) */ 182 | for (i=16; i<32; i++) 183 | x[i] = rand[i-16]; 184 | 185 | /* ( Loop eight times ) */ 186 | for (i=1; i<9; i++) { 187 | /* ( Load key into first 16 bytes of input ) */ 188 | for (j=0; j<16; j++) 189 | x[j] = key[j]; 190 | /* ( Perform substitutions ) */ 191 | for (j=0; j<5; j++) 192 | for (k=0; k<(1<>(3-k)) & 1; 205 | /* ( Permutation but not on the last loop ) */ 206 | if (i < 8) 207 | for (j=0; j<16; j++) { 208 | x[j+16] = 0; 209 | for (k=0; k<8; k++) { 210 | next_bit = ((8*j + k)*17) % 128; 211 | x[j+16] |= bit[next_bit] << (7-k); 212 | } 213 | } 214 | } 215 | 216 | /* 217 | * ( At this stage the vector x[] consists of 32 nibbles. 218 | * The first 8 of these are taken as the output SRES. ) 219 | */ 220 | 221 | /* The remainder of the code is not given explicitly in the 222 | * standard, but was derived by reverse-engineering. 223 | */ 224 | 225 | for (i=0; i<4; i++) 226 | simoutput[i] = (x[2*i]<<4) | x[2*i+1]; 227 | for (i=0; i<6; i++) 228 | simoutput[4+i] = (x[2*i+18]<<6) | (x[2*i+18+1]<<2) 229 | | (x[2*i+18+2]>>2); 230 | simoutput[4+6] = (x[2*6+18]<<6) | (x[2*6+18+1]<<2); 231 | simoutput[4+7] = 0; 232 | } 233 | 234 | 235 | int hextoint(char x) 236 | { 237 | x = toupper(x); 238 | if (x >= 'A' && x <= 'F') 239 | return x-'A'+10; 240 | else if (x >= '0' && x <= '9') 241 | return x-'0'; 242 | fprintf(stderr, "bad input.\n"); 243 | exit(1); 244 | } 245 | 246 | int main(int argc, char **argv) 247 | { 248 | Byte key[16], rand[16], simoutput[12]; 249 | int i; 250 | 251 | if (argc != 3 || strlen(argv[1]) != 34 || strlen(argv[2]) != 34 252 | || strncmp(argv[1], "0x", 2) != 0 253 | || strncmp(argv[2], "0x", 2) != 0) { 254 | fprintf(stderr, "Usage: %s 0x<32-digit-key> 0x<32-digit-rand>\n", argv[0]); 255 | printf("error\n"); 256 | exit(1); 257 | } 258 | 259 | for (i=0; i<16; i++) 260 | key[i] = (hextoint(argv[1][2*i+2])<<4) 261 | | hextoint(argv[1][2*i+3]); 262 | for (i=0; i<16; i++) 263 | rand[i] = (hextoint(argv[2][2*i+2])<<4) 264 | | hextoint(argv[2][2*i+3]); 265 | A3A8(rand, key, simoutput); 266 | for (i=0; i<12; i++) 267 | printf("%02X", simoutput[i]); 268 | printf("\n"); 269 | return 0; 270 | } 271 | -------------------------------------------------------------------------------- /apps/hexmapper: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | # this normalizes things that are ok to change, like random numbers (which it numbers 7 | # in the order found to keep relative values correct), SRESs (ditto), dates, and PIDs. 8 | # And source code line numbers. 9 | 10 | my($hexN) = 1000; 11 | my(%mapping); 12 | 13 | sub hexmap { 14 | my($in) = @_; 15 | my($out) = $mapping{$in}; 16 | if (!defined($out)) { 17 | $out = substr("hexhexhexhexhexhexhexhexhexhexhex", 0, length($in) - 4) . $hexN; 18 | $mapping{$in} = $out; 19 | $hexN++; 20 | } 21 | return $out; 22 | } 23 | 24 | sub main { 25 | my($first) = 1; 26 | while (<>) { 27 | # normalize big (random) hex numbers 28 | s/\b([0-9a-fA-F]{32})\b/&hexmap($1)/ge; # RAND and Ki size 29 | s/\b([0-9a-fA-F]{24})\b/&hexmap($1)/ge; # simout size 30 | s/\b([0-9a-fA-F]{8})\b/&hexmap($1)/ge; # SRES size 31 | # normalize dates 32 | if ($first) { 33 | $first = 0; 34 | } else { 35 | s/[A-Z][a-z][a-z] [A-Z][a-z][a-z] (\d| )\d \d\d:\d\d:\d\d (P[DS]T )?201\d/-DATE-/; 36 | } 37 | # normalize PIDs 38 | s/(subscriberregistry\.[12])\.\d+/$1.-PID-/g; 39 | # normalize source code line numbers 40 | s/(\.cpp):(\d+):/$1:-0-:/; 41 | print; 42 | } 43 | } 44 | 45 | &main; 46 | -------------------------------------------------------------------------------- /apps/sipauthserve.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Kestrel Signal Processing, Inc. 3 | * Copyright 2011, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under the terms of the GNU Affero Public License. 6 | * See the COPYING file in the main directory for details. 7 | * 8 | * This use of this software may be subject to additional restrictions. 9 | * See the LEGAL file in the main directory for details. 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU Affero General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Affero General Public License for more details. 20 | 21 | You should have received a copy of the GNU Affero General Public License 22 | along with this program. If not, see . 23 | 24 | */ 25 | 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include "servershare.h" 51 | #include "SubscriberRegistry.h" 52 | 53 | using namespace std; 54 | 55 | ConfigurationTable gConfig("/etc/OpenBTS/sipauthserve.db", "sipauthserve", getConfigurationKeys()); 56 | Log dummy("sipauthserve", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7); 57 | 58 | int my_udp_port; 59 | 60 | // just using this for the database access 61 | SubscriberRegistry gSubscriberRegistry; 62 | 63 | /** The remote node manager. */ 64 | NodeManager gNodeManager; 65 | 66 | /** The JSON<->DB interface. */ 67 | JSONDB gJSONDB; 68 | 69 | /** Application specific NodeManager logic for handling requests. */ 70 | JsonBox::Object nmHandler(JsonBox::Object& request) 71 | { 72 | JsonBox::Object response; 73 | std::string command = request["command"].getString(); 74 | std::string action = request["action"].getString(); 75 | 76 | if (command.compare("subscribers") == 0) { 77 | request["table"] = JsonBox::Value("subscribers"); 78 | response = gJSONDB.query(request); 79 | } else { 80 | response["code"] = JsonBox::Value(501); 81 | } 82 | 83 | return response; 84 | } 85 | 86 | void prettyPrint(const char *label, osip_message_t *sip) 87 | { 88 | char *dest=NULL; 89 | size_t length=0; 90 | int i = osip_message_to_str(sip, &dest, &length); 91 | if (i!=0) { 92 | LOG(ERR) << "cannot get printable message"; 93 | } else { 94 | LOG(INFO) << label << ":\n" << dest; 95 | osip_free(dest); 96 | } 97 | } 98 | 99 | string imsiFromSip(osip_message_t *sip) 100 | { 101 | char *dest; 102 | osip_uri_t *fromUri = osip_from_get_url(sip->from); 103 | if (!fromUri) { 104 | LOG(ERR) << "osip_from_get_url problem"; 105 | return ""; 106 | } 107 | osip_uri_to_str(fromUri, &dest); 108 | string imsi = dest; 109 | osip_free(dest); 110 | return imsi; 111 | } 112 | 113 | string imsiToSip(osip_message_t *sip) 114 | { 115 | char *dest; 116 | osip_uri_t *toUri = osip_to_get_url(sip->to); 117 | if (!toUri) { 118 | LOG(ERR) << "osip_to_get_url problem"; 119 | return ""; 120 | } 121 | osip_uri_to_str(toUri, &dest); 122 | string imsi = dest; 123 | osip_free(dest); 124 | return imsi; 125 | } 126 | 127 | // is imsi in the database? 128 | bool imsiFound(string imsi) 129 | { 130 | string x = gSubscriberRegistry.imsiGet(imsi, "id"); 131 | return x.length() != 0; 132 | } 133 | 134 | string imsiClean(string imsi) 135 | { 136 | // remove leading sip: 137 | if (0 == strncasecmp(imsi.c_str(), "sip:", 4)) { 138 | imsi = imsi.substr(4); 139 | } 140 | // remove trailing @... 141 | size_t p = imsi.find("@"); 142 | if (p != string::npos) { 143 | imsi = imsi.substr(0, p); 144 | } 145 | // remove leading IMSI 146 | if (0 == strncasecmp(imsi.c_str(), "imsi", 4)) { 147 | imsi = imsi.substr(4); 148 | } 149 | return imsi; 150 | } 151 | 152 | 153 | char *processBuffer(char *buffer) 154 | { 155 | int i; 156 | 157 | // parse sip message 158 | osip_message_t *sip; 159 | i=osip_message_init(&sip); 160 | if (i!=0) { 161 | LOG(ERR) << "cannot allocate"; 162 | osip_message_free(sip); 163 | return NULL; 164 | } 165 | i=osip_message_parse(sip, buffer, strlen(buffer)); 166 | if (i!=0) { 167 | LOG(ERR) << "cannot parse sip message"; 168 | osip_message_free(sip); 169 | return NULL; 170 | } 171 | 172 | prettyPrint("request", sip); 173 | 174 | // response starts as clone of message 175 | osip_message_t *response; 176 | osip_message_clone(sip, &response); 177 | 178 | osip_from_t * contact_header = (osip_from_t*)osip_list_get(&sip->contacts,0); 179 | osip_uri_t* contact_url = contact_header->url; 180 | char *remote_host = contact_url->host; 181 | char *remote_port = contact_url->port; 182 | 183 | // return via 184 | ostringstream newvia; 185 | // newvia << "SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar"; 186 | const char *my_ipaddress = "localhost"; 187 | newvia << "SIP/2.0/UDP " << my_ipaddress << ":" << my_udp_port << ";branch=1;received=" 188 | << "string_address@foo.bar"; // << my_network.string_addr((struct sockaddr *)netaddr, netaddrlen, false); 189 | osip_message_append_via(response, newvia.str().c_str()); 190 | 191 | // no method 192 | osip_message_set_method(response, NULL); 193 | 194 | string imsi = imsiClean(imsiFromSip(sip)); 195 | string imsiTo = imsiClean(imsiToSip(sip)); 196 | if ((imsi == "EXIT") && (imsiTo == "EXIT")) exit(0); // for testing only 197 | if (!imsiFound(imsi)) { 198 | LOG(NOTICE) << "imsi unknown"; 199 | // imsi problem => 404 IMSI Not Found 200 | osip_message_set_status_code (response, 404); 201 | osip_message_set_reason_phrase (response, osip_strdup("IMSI Not Found")); 202 | } else if (gConfig.defines("SubscriberRegistry.IgnoreAuthentication")) { 203 | osip_message_set_status_code (response, 200); 204 | osip_message_set_reason_phrase (response, osip_strdup("OK")); 205 | LOG(INFO) << "success, imsi " << imsi << " registering for IP address " << remote_host; 206 | gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port); 207 | } else { 208 | // look for rand and sres in Authorization header (assume imsi same as in from) 209 | string randx; 210 | string sres; 211 | // sip parser is not working reliably for Authorization, so we'll do the parsing 212 | char *RAND = strcasestr(buffer, "nonce="); 213 | char *SRES = strcasestr(buffer, "response="); 214 | if (RAND && SRES) { 215 | // find RAND digits 216 | RAND += 6; 217 | while (!isalnum(*RAND)) { RAND++; } 218 | RAND[32] = 0; 219 | int j=0; 220 | // FIXME -- These loops should use strspn instead. 221 | while(isalnum(RAND[j])) { j++; } 222 | RAND[j] = '\0'; 223 | // find SRES digits 224 | SRES += 9; 225 | while (!isalnum(*SRES)) { SRES++; } 226 | int i=0; 227 | // FIXME -- These loops should use strspn instead. 228 | while(isalnum(SRES[i])) { i++; } 229 | SRES[i] = '\0'; 230 | LOG(INFO) << "rand = /" << RAND << "/"; 231 | LOG(INFO) << "sres = /" << SRES << "/"; 232 | } 233 | if (!RAND || !SRES) { 234 | LOG(NOTICE) << "imsi " << imsi << " known, 1st register"; 235 | // no rand and sres => 401 Unauthorized 236 | osip_message_set_status_code (response, 401); 237 | osip_message_set_reason_phrase (response, osip_strdup("Unauthorized")); 238 | // but include rand in www_authenticate 239 | osip_www_authenticate_t *auth; 240 | osip_www_authenticate_init(&auth); 241 | // auth type is required by osip_www_authenticate_to_str (and therefore osip_message_to_str) 242 | string auth_type = "Digest"; 243 | osip_www_authenticate_set_auth_type(auth, osip_strdup(auth_type.c_str())); 244 | // returning RAND in www_authenticate header 245 | string randz = generateRand(imsi); 246 | osip_www_authenticate_set_nonce(auth, osip_strdup(randz.c_str())); 247 | i = osip_list_add (&response->www_authenticates, auth, -1); 248 | if (i < 0) LOG(ERR) << "problem adding www_authenticate"; 249 | } else { 250 | string kc; 251 | bool sres_good = authenticate(imsi, RAND, SRES, &kc); 252 | LOG(INFO) << "imsi " << imsi << " known, 2nd register, good = " << sres_good; 253 | if (sres_good) { 254 | // sres matches rand => 200 OK 255 | osip_message_set_status_code (response, 200); 256 | osip_message_set_reason_phrase (response, osip_strdup("OK")); 257 | if (kc.size() != 0) { 258 | osip_authentication_info *auth; 259 | osip_authentication_info_init(&auth); 260 | osip_authentication_info_set_cnonce(auth, osip_strdup(kc.c_str())); 261 | i = osip_list_add (&response->authentication_infos, auth, -1); 262 | if (i < 0) LOG(ERR) << "problem adding authentication_infos"; 263 | } 264 | // (pat 9-2013) Add the caller id. 265 | static string calleridstr("callerid"); 266 | string callid = gSubscriberRegistry.imsiGet(imsi,calleridstr); 267 | if (callid.size()) { 268 | char buf[120]; 269 | // Per RFC3966 the telephone numbers should begin with "+" only if it is globally unique throughout the world. 270 | // We should not add the "+" here, it should be in the database if appropriate. 271 | snprintf(buf,120,"",callid.c_str()); 272 | osip_message_set_header(response,"P-Associated-URI",buf); 273 | } 274 | // And register it. 275 | LOG(INFO) << "success, registering for IP address " << remote_host; 276 | gSubscriberRegistry.imsiSet(imsi,"ipaddr", remote_host, "port", remote_port); 277 | } else { 278 | // sres does not match rand => 401 Unauthorized 279 | osip_message_set_status_code (response, 401); 280 | osip_message_set_reason_phrase (response, osip_strdup("Unauthorized")); 281 | } 282 | } 283 | } 284 | 285 | prettyPrint("response", response); 286 | size_t length = 0; 287 | char *dest; 288 | int ii = osip_message_to_str(response, &dest, &length); 289 | if (ii != 0) { 290 | LOG(ERR) << "cannot get printable message"; 291 | } 292 | 293 | osip_message_free(sip); 294 | osip_message_free(response); 295 | 296 | return dest; 297 | } 298 | 299 | 300 | #define BUFLEN 5000 301 | 302 | int 303 | main(int argc, char **argv) 304 | { 305 | // TODO: Properly parse and handle any arguments 306 | if (argc > 1) { 307 | for (int argi = 0; argi < argc; argi++) { 308 | if (!strcmp(argv[argi], "--version") || 309 | !strcmp(argv[argi], "-v")) { 310 | cout << gVersionString << endl; 311 | } 312 | if (!strcmp(argv[argi], "--gensql")) { 313 | cout << gConfig.getDefaultSQL(string(argv[0]), gVersionString) << endl; 314 | } 315 | if (!strcmp(argv[argi], "--gentex")) { 316 | cout << gConfig.getTeX(string(argv[0]), gVersionString) << endl; 317 | } 318 | } 319 | 320 | return 0; 321 | } 322 | 323 | sockaddr_in si_me; 324 | sockaddr_in si_other; 325 | int aSocket; 326 | char buf[BUFLEN]; 327 | 328 | LOG(ALERT) << argv[0] << " (re)starting"; 329 | srand ( time(NULL) + (int)getpid() ); 330 | my_udp_port = gConfig.getNum("SubscriberRegistry.Port"); 331 | gSubscriberRegistry.init(); 332 | gNodeManager.setAppLogicHandler(&nmHandler); 333 | gNodeManager.start(45064); 334 | 335 | // init osip lib 336 | osip_t *osip; 337 | int i=osip_init(&osip); 338 | if (i!=0) { 339 | LOG(ALERT) << "cannot init sip lib"; 340 | exit(1); 341 | } 342 | 343 | if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { 344 | LOG(ALERT) << "can't initialize socket"; 345 | exit(1); 346 | } 347 | 348 | memset((char *) &si_me, 0, sizeof(si_me)); 349 | si_me.sin_family = AF_INET; 350 | si_me.sin_port = htons(my_udp_port); 351 | si_me.sin_addr.s_addr = htonl(INADDR_ANY); 352 | if (bind(aSocket, (sockaddr*)&si_me, sizeof(si_me)) == -1) { 353 | LOG(ALERT) << "can't bind socket on port " << my_udp_port; 354 | exit(1); 355 | } 356 | 357 | LOG(NOTICE) << "binding on port " << my_udp_port; 358 | 359 | while (true) { 360 | gConfig.purge(); 361 | socklen_t slen = sizeof(si_other); 362 | memset(buf, 0, BUFLEN); 363 | if (recvfrom(aSocket, buf, BUFLEN, 0, (sockaddr*)&si_other, &slen) == -1) { 364 | LOG(ERR) << "recvfrom problem"; 365 | continue; 366 | } 367 | 368 | LOG(INFO) << " receiving " << buf; 369 | 370 | char *dest = processBuffer(buf); 371 | if (dest == NULL) { 372 | continue; 373 | } 374 | 375 | if (sendto(aSocket, dest, strlen(dest), 0, (sockaddr*)&si_other, sizeof(si_other)) == -1) { 376 | LOG(ERR) << "sendto problem"; 377 | continue; 378 | } 379 | osip_free(dest); 380 | } 381 | 382 | close(aSocket); 383 | return 0; 384 | } 385 | -------------------------------------------------------------------------------- /apps/syslogextractor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | sub poot2 { 7 | my($line) = @_; 8 | # sip message printing adds the \r stuff. Get rid of it. 9 | $line =~ s/\\r//g; 10 | print "$line\n"; 11 | } 12 | 13 | sub poot { 14 | my($buf) = @_; 15 | # sip message printing comes in one big chunk. Split the lines. 16 | my(@buf) = split('\\\\n', $buf); 17 | &poot2($_) foreach @buf; 18 | } 19 | 20 | sub main { 21 | open(IN, "/var/log/OpenBTS.log") || die; 22 | my(@out); 23 | while () { 24 | chomp; 25 | # Ignore everything before the latest mark. 26 | if (/dwb syslog mark/) { 27 | @out = (); 28 | next; 29 | } 30 | if (/: INFO (0x[0-9a-fA-F]+|\d+) (.+)/) { 31 | # clean out garbage fro INFO lines 32 | push(@out, $2); 33 | } else { 34 | # keep all of other lines. (might be ERR or EMERG, e.g.) 35 | push(@out, $_); 36 | } 37 | } 38 | close(IN); 39 | poot $_ foreach @out; 40 | } 41 | 42 | &main; 43 | -------------------------------------------------------------------------------- /config/Makefile.am: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2008 Free Software Foundation, Inc. 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This software is distributed under the terms of the GNU Public License. 6 | # See the COPYING file in the main directory for details. 7 | # 8 | # This program is free software: you can redistribute it and/or modify 9 | # it under the terms of the GNU General Public License as published by 10 | # the Free Software Foundation, either version 3 of the License, or 11 | # (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program. If not, see . 20 | # 21 | 22 | include $(top_srcdir)/Makefile.common 23 | 24 | # Install m4 macros in this directory 25 | m4datadir = $(datadir)/aclocal 26 | 27 | # List your m4 macros here 28 | m4macros = \ 29 | pkg.m4 30 | 31 | EXTRA_DIST = $(m4macros) 32 | -------------------------------------------------------------------------------- /config/pkg.m4: -------------------------------------------------------------------------------- 1 | # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- 2 | # 3 | # Copyright © 2004 Scott James Remnant . 4 | # Copyright © 2008 Free Software Foundation, Inc. 5 | # 6 | # This program is free software; you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation; either version 2 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, but 12 | # WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | # General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | # 20 | # As a special exception to the GNU General Public License, if you 21 | # distribute this file as part of a program that contains a 22 | # configuration script generated by Autoconf, you may include it under 23 | # the same distribution terms that you use for the rest of that program. 24 | 25 | # PKG_PROG_PKG_CONFIG([MIN-VERSION]) 26 | # ---------------------------------- 27 | AC_DEFUN([PKG_PROG_PKG_CONFIG], 28 | [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) 29 | m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) 30 | AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl 31 | if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then 32 | AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) 33 | fi 34 | if test -n "$PKG_CONFIG"; then 35 | _pkg_min_version=m4_default([$1], [0.18]) 36 | AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) 37 | if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then 38 | AC_MSG_RESULT([yes]) 39 | else 40 | AC_MSG_RESULT([no]) 41 | PKG_CONFIG="" 42 | fi 43 | 44 | fi[]dnl 45 | ])# PKG_PROG_PKG_CONFIG 46 | 47 | # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) 48 | # 49 | # Check to see whether a particular set of modules exists. Similar 50 | # to PKG_CHECK_MODULES(), but does not set variables or print errors. 51 | # 52 | # 53 | # Similar to PKG_CHECK_MODULES, make sure that the first instance of 54 | # this or PKG_CHECK_MODULES is called, or make sure to call 55 | # PKG_CHECK_EXISTS manually 56 | # -------------------------------------------------------------- 57 | AC_DEFUN([PKG_CHECK_EXISTS], 58 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 59 | if test -n "$PKG_CONFIG" && \ 60 | AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then 61 | m4_ifval([$2], [$2], [:]) 62 | m4_ifvaln([$3], [else 63 | $3])dnl 64 | fi]) 65 | 66 | 67 | # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) 68 | # --------------------------------------------- 69 | m4_define([_PKG_CONFIG], 70 | [if test -n "$PKG_CONFIG"; then 71 | if test -n "$$1"; then 72 | pkg_cv_[]$1="$$1" 73 | else 74 | PKG_CHECK_EXISTS([$3], 75 | [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], 76 | [pkg_failed=yes]) 77 | fi 78 | else 79 | pkg_failed=untried 80 | fi[]dnl 81 | ])# _PKG_CONFIG 82 | 83 | # _PKG_SHORT_ERRORS_SUPPORTED 84 | # ----------------------------- 85 | AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], 86 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) 87 | if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then 88 | _pkg_short_errors_supported=yes 89 | else 90 | _pkg_short_errors_supported=no 91 | fi[]dnl 92 | ])# _PKG_SHORT_ERRORS_SUPPORTED 93 | 94 | 95 | # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], 96 | # [ACTION-IF-NOT-FOUND]) 97 | # 98 | # E.g., 99 | # PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) 100 | # defines: 101 | # 102 | # GSTUFF_LIBS 103 | # GSTUFF_CFLAGS 104 | # GSTUFF_INCLUDEDIR 105 | # GSTUFF_CPPFLAGS # the -I, -D and -U's out of CFLAGS 106 | # 107 | # see pkg-config man page also defines GSTUFF_PKG_ERRORS on error 108 | # 109 | # Note that if there is a possibility the first call to 110 | # PKG_CHECK_MODULES might not happen, you should be sure to include an 111 | # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac 112 | # 113 | # -------------------------------------------------------------- 114 | AC_DEFUN([PKG_CHECK_MODULES], 115 | [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl 116 | AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl 117 | AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl 118 | AC_ARG_VAR([$1][_INCLUDEDIR], [includedir for $1, overriding pkg-config])dnl 119 | 120 | pkg_failed=no 121 | AC_MSG_CHECKING([for $1]) 122 | 123 | _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) 124 | 125 | if test x$cross_compiling = xyes 126 | then 127 | _PKG_CONFIG([$1][_LIBS], [libs-only-l --static], [$2]) 128 | else 129 | _PKG_CONFIG([$1][_LIBS], [libs --static], [$2]) 130 | fi 131 | 132 | _PKG_CONFIG([$1][_INCLUDEDIR], [variable=includedir], [$2]) 133 | 134 | 135 | m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS 136 | and $1[]_LIBS to avoid the need to call pkg-config. 137 | See the pkg-config man page for more details.]) 138 | 139 | if test $pkg_failed = yes; then 140 | _PKG_SHORT_ERRORS_SUPPORTED 141 | if test $_pkg_short_errors_supported = yes; then 142 | $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` 143 | else 144 | $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` 145 | fi 146 | # Put the nasty error message in config.log where it belongs 147 | echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD 148 | 149 | ifelse([$4], , [AC_MSG_ERROR(dnl 150 | [Package requirements ($2) were not met: 151 | 152 | $$1_PKG_ERRORS 153 | 154 | Consider adjusting the PKG_CONFIG_PATH environment variable if you 155 | installed software in a non-standard prefix. 156 | 157 | _PKG_TEXT 158 | ])], 159 | [AC_MSG_RESULT([no]) 160 | $4]) 161 | elif test $pkg_failed = untried; then 162 | ifelse([$4], , [AC_MSG_FAILURE(dnl 163 | [The pkg-config script could not be found or is too old. Make sure it 164 | is in your PATH or set the PKG_CONFIG environment variable to the full 165 | path to pkg-config. 166 | 167 | _PKG_TEXT 168 | 169 | To get pkg-config, see .])], 170 | [$4]) 171 | else 172 | $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS 173 | $1[]_LIBS=$pkg_cv_[]$1[]_LIBS 174 | $1[]_INCLUDEDIR=$pkg_cv_[]$1[]_INCLUDEDIR 175 | 176 | $1[]_CPPFLAGS="" 177 | for flag in $$1[]_CFLAGS; do 178 | case $flag in 179 | -I* | -D* | -U*) $1[]_CPPFLAGS="$$1[]_CPPFLAGS $flag" ;; 180 | esac 181 | done 182 | pkg_cv_[]$1[]_CPPFLAGS=$$1[]_CPPFLAGS 183 | AC_SUBST($1[]_CPPFLAGS) 184 | 185 | AC_MSG_RESULT([yes]) 186 | ifelse([$3], , :, [$3]) 187 | fi[]dnl 188 | ])# PKG_CHECK_MODULES 189 | -------------------------------------------------------------------------------- /configFiles/odbc.ini: -------------------------------------------------------------------------------- 1 | [asterisk] 2 | Description=SQLite3 database 3 | Driver=SQLite3 4 | Database=/var/lib/asterisk/sqlite3dir/sqlite3.db 5 | # optional lock timeout in milliseconds 6 | Timeout=2000 7 | -------------------------------------------------------------------------------- /configFiles/odbcinst.ini: -------------------------------------------------------------------------------- 1 | [SQLite3] 2 | Description=SQLite3 ODBC Driver 3 | Driver=/usr/local/lib/libsqlite3odbc.so 4 | Setup=/usr/local/lib/libsqlite3odbc.so 5 | Threading=2 6 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | dnl 2 | dnl Copyright 2008, 2009, 2010 Free Software Foundation, Inc. 3 | dnl Copyright 2014 Range Networks, Inc. 4 | dnl 5 | dnl This software is distributed under the terms of the GNU Public License. 6 | dnl See the COPYING file in the main directory for details. 7 | dnl 8 | dnl This program is free software: you can redistribute it and/or modify 9 | dnl it under the terms of the GNU General Public License as published by 10 | dnl the Free Software Foundation, either version 3 of the License, or 11 | dnl (at your option) any later version. 12 | dnl 13 | dnl This program is distributed in the hope that it will be useful, 14 | dnl but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | dnl GNU General Public License for more details. 17 | dnl 18 | dnl You should have received a copy of the GNU General Public License 19 | dnl along with this program. If not, see . 20 | dnl 21 | 22 | AC_PREREQ(2.57) 23 | AC_INIT(sipauthserve,5.0-master) 24 | 25 | AC_CANONICAL_BUILD 26 | AC_CANONICAL_HOST 27 | AC_CANONICAL_TARGET 28 | 29 | AC_CONFIG_AUX_DIR([.]) 30 | AM_INIT_AUTOMAKE([-Wno-portability]) 31 | AC_CONFIG_HEADERS([config.h]) 32 | AC_CONFIG_MACRO_DIR([config]) 33 | AC_CONFIG_SRCDIR([SubscriberRegistry.cpp]) 34 | 35 | AM_PROG_AS 36 | AC_PROG_CXX 37 | AC_PROG_LN_S 38 | AC_PROG_MAKE_SET 39 | AC_PROG_INSTALL 40 | AC_PATH_PROG([RM_PROG], [rm]) 41 | 42 | AC_LIBTOOL_WIN32_DLL 43 | AC_ENABLE_SHARED dnl do build shared libraries 44 | AC_DISABLE_STATIC dnl don't build static libraries 45 | AC_PROG_LIBTOOL 46 | 47 | dnl Checks for header files. 48 | AC_HEADER_STDC 49 | dnl This is required for GnuRadio includes to understand endianess correctly: 50 | AC_CHECK_HEADERS([byteswap.h]) 51 | 52 | dnl Checks for typedefs, structures, and compiler characteristics. 53 | AC_C_CONST 54 | AC_C_INLINE 55 | AC_TYPE_SIZE_T 56 | AC_HEADER_TIME 57 | AC_C_BIGENDIAN 58 | 59 | dnl Check for libzmq 60 | if test ! -r "/usr/include/zmq.h" -a ! -r "/usr/local/include/zmq.h"; then 61 | AC_MSG_ERROR([/usr/local/include/zmq.h not found. Install the libzmq3-dev package manually or run $ sudo ./NodeManager/install_libzmq.sh]) 62 | fi 63 | if test ! -r "/usr/include/zmq.hpp" -a ! -r "/usr/local/include/zmq.hpp"; then 64 | AC_MSG_ERROR([/usr/local/include/zmq.hpp not found. Install the libzmq3-dev package manually or run $ sudo ./NodeManager/install_libzmq.sh]) 65 | fi 66 | AC_CHECK_LIB(zmq, zmq_init, ,[AC_MSG_ERROR([Cannot link with -lzmq. Install the libzmq3-dev package manually or run $ sudo ./NodeManager/install_libzmq.sh])]) 67 | AC_MSG_CHECKING([whether libzmq installation works]) 68 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], 69 | [zmq_init(1);]) 70 | ], 71 | [AC_MSG_RESULT([yes])], 72 | [AC_MSG_ERROR([no. Install the libzmq3-dev package manually or run $ sudo ./NodeManager/install_libzmq.sh])]) 73 | 74 | # Check for glibc-specific network functions 75 | AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAVE_GETHOSTBYNAME_R, 1, Define if libc implements gethostbyname_r)]) 76 | AC_CHECK_FUNC(gethostbyname2_r, [AC_DEFINE(HAVE_GETHOSTBYNAME2_R, 1, Define if libc implements gethostbyname2_r)]) 77 | 78 | dnl Output files 79 | AC_CONFIG_FILES([\ 80 | Makefile \ 81 | apps/Makefile \ 82 | config/Makefile \ 83 | CommonLibs/Makefile \ 84 | Globals/Makefile \ 85 | NodeManager/Makefile \ 86 | ]) 87 | 88 | AC_OUTPUT 89 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | sipauthserve (5.0) unstable; urgency=low 2 | 3 | * Test 4 | 5 | -- Range Packager Thu, 25 Sep 2014 00:17:42 -0700 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 7 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: sipauthserve 2 | Section: comm 3 | Priority: optional 4 | Maintainer: Range Networks, Inc. 5 | Homepage: http://www.rangenetworks.com/ 6 | Build-Depends: build-essential, debhelper (>= 7), libsqlite3-dev, libosip2-dev, pkg-config, autoconf, libtool, libzmq3-dev, libzmq3 | libzmq5 7 | Standards-Version: 3.7.3 8 | 9 | Package: sipauthserve 10 | Section: comm 11 | Priority: optional 12 | Architecture: any 13 | Essential: no 14 | Depends: sqlite3, libosip2-dev, libc6, pkg-config, libzmq3 | libzmq5 15 | Description: Range Networks - SIP Authorization Server 16 | 17 | -------------------------------------------------------------------------------- /debian/dirs: -------------------------------------------------------------------------------- 1 | var/lib/asterisk/sqlite3dir 2 | etc/OpenBTS 3 | OpenBTS 4 | -------------------------------------------------------------------------------- /debian/links: -------------------------------------------------------------------------------- 1 | usr/local/sbin/comp128 OpenBTS/comp128 2 | usr/local/sbin/sipauthserve OpenBTS/sipauthserve 3 | -------------------------------------------------------------------------------- /debian/postinst: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # postinst script for test 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `configure' 10 | # * `abort-upgrade' 11 | # * `abort-remove' `in-favour' 12 | # 13 | # * `abort-remove' 14 | # * `abort-deconfigure' `in-favour' 15 | # `removing' 16 | # 17 | # for details, see http://www.debian.org/doc/debian-policy/ or 18 | # the debian-policy package 19 | 20 | configure() 21 | { 22 | WEBUSER=www-data 23 | DATE=$(date --rfc-3339='date') 24 | 25 | CONFIG_BACKUP=/etc/OpenBTS/sipauthserve.dump-$DATE 26 | if [ ! -e $CONFIG_BACKUP ]; then 27 | sqlite3 /etc/OpenBTS/sipauthserve.db ".dump" > $CONFIG_BACKUP 28 | fi 29 | 30 | sqlite3 /etc/OpenBTS/sipauthserve.db ".read /etc/OpenBTS/sipauthserve.example.sql" > /dev/null 2>&1 31 | 32 | SRPATH=/var/lib/asterisk/sqlite3dir/sqlite3.db 33 | SR_BACKUP=$SRPATH.dump-$DATE 34 | 35 | if [[ -e $SRPATH && "`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" || true`" != "" ]]; then 36 | if [ ! -e $SR_BACKUP ]; then 37 | sqlite3 $SRPATH ".dump" > $SR_BACKUP 38 | fi 39 | 40 | HASPREPAID=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep prepaid || true` 41 | if [ "$HASPREPAID" = "" ]; then 42 | sqlite3 $SRPATH "alter table sip_buddies add prepaid int(1) DEFAULT 0 not null" 43 | fi 44 | 45 | HASBALANCE=`sqlite3 $SRPATH "PRAGMA table_info(sip_buddies)" | grep account_balance || true` 46 | if [ "$HASBALANCE" = "" ]; then 47 | sqlite3 $SRPATH "alter table sip_buddies add column account_balance int(9) default 0" 48 | fi 49 | 50 | sqlite3 $SRPATH "create table if not exists rates (service varchar(30) unique not null, rate integer not null)" 51 | sqlite3 $SRPATH "insert or ignore into 'rates' values ('in-network-SMS', 10)" 52 | sqlite3 $SRPATH "insert or ignore into 'rates' values ('out-of-network-SMS', 20)" 53 | sqlite3 $SRPATH "insert or ignore into 'rates' values ('in-network-call', 1)" 54 | sqlite3 $SRPATH "insert or ignore into 'rates' values ('out-of-network-call', 1)" 55 | fi 56 | 57 | # directory permissions 58 | chown -R root:${WEBUSER} /var/lib/asterisk/sqlite3dir 59 | chmod -R ug+rw /var/lib/asterisk/sqlite3dir/ 60 | chmod -R o-w /var/lib/asterisk/sqlite3dir/ 61 | } 62 | 63 | case "$1" in 64 | configure) 65 | configure 66 | ;; 67 | 68 | abort-upgrade|abort-remove|abort-deconfigure) 69 | ;; 70 | 71 | *) 72 | echo "postinst called with unknown argument \`$1'" >&2 73 | exit 1 74 | ;; 75 | esac 76 | 77 | # dh_installdeb will replace this with shell code automatically 78 | # generated by other debhelper scripts. 79 | 80 | #DEBHELPER# 81 | 82 | exit 0 83 | -------------------------------------------------------------------------------- /debian/postrm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # postrm script for test 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `remove' 10 | # * `purge' 11 | # * `upgrade' 12 | # * `failed-upgrade' 13 | # * `abort-install' 14 | # * `abort-install' 15 | # * `abort-upgrade' 16 | # * `disappear' 17 | # 18 | # for details, see http://www.debian.org/doc/debian-policy/ or 19 | # the debian-policy package 20 | 21 | 22 | case "$1" in 23 | purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) 24 | ;; 25 | 26 | *) 27 | echo "postrm called with unknown argument \`$1'" >&2 28 | exit 1 29 | ;; 30 | esac 31 | 32 | # dh_installdeb will replace this with shell code automatically 33 | # generated by other debhelper scripts. 34 | 35 | #DEBHELPER# 36 | 37 | exit 0 38 | -------------------------------------------------------------------------------- /debian/preinst: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # preinst script for test 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `install' 10 | # * `install' 11 | # * `upgrade' 12 | # * `abort-upgrade' 13 | # for details, see http://www.debian.org/doc/debian-policy/ or 14 | # the debian-policy package 15 | 16 | 17 | case "$1" in 18 | install|upgrade) 19 | ;; 20 | 21 | abort-upgrade) 22 | ;; 23 | 24 | *) 25 | echo "preinst called with unknown argument \`$1'" >&2 26 | exit 1 27 | ;; 28 | esac 29 | 30 | # dh_installdeb will replace this with shell code automatically 31 | # generated by other debhelper scripts. 32 | 33 | #DEBHELPER# 34 | 35 | exit 0 36 | -------------------------------------------------------------------------------- /debian/prerm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # prerm script for test 3 | # 4 | # see: dh_installdeb(1) 5 | 6 | set -e 7 | 8 | # summary of how this script can be called: 9 | # * `remove' 10 | # * `upgrade' 11 | # * `failed-upgrade' 12 | # * `remove' `in-favour' 13 | # * `deconfigure' `in-favour' 14 | # `removing' 15 | # 16 | # for details, see http://www.debian.org/doc/debian-policy/ or 17 | # the debian-policy package 18 | 19 | case "$1" in 20 | remove|upgrade|deconfigure) 21 | set +e 22 | stop sipauthserve 23 | set -e 24 | ;; 25 | 26 | failed-upgrade) 27 | ;; 28 | 29 | *) 30 | echo "prerm called with unknown argument \`$1'" >&2 31 | exit 1 32 | ;; 33 | esac 34 | 35 | # dh_installdeb will replace this with shell code automatically 36 | # generated by other debhelper scripts. 37 | 38 | #DEBHELPER# 39 | 40 | exit 0 41 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # 5 | # This file was originally written by Joey Hess and Craig Small. 6 | # As a special exception, when this file is copied by dh-make into a 7 | # dh-make output file, you may use that output file without restriction. 8 | # This special exception was added by Craig Small in version 0.37 of dh-make. 9 | # 10 | # Modified to make a template file for a multi-binary package with separated 11 | # build-arch and build-indep targets by Bill Allombert 2001 12 | 13 | # Uncomment this to turn on verbose mode. 14 | export DH_VERBOSE=0 15 | 16 | # Never distribute source control meta information 17 | export DH_ALWAYS_EXCLUDE=.svn:.git 18 | 19 | # This has to be exported to make some magic below work. 20 | export DH_OPTIONS 21 | 22 | configure: 23 | ./autogen.sh # --verbose 24 | 25 | config: configure-stamp 26 | configure-stamp: configure 27 | dh_testdir 28 | # Add here commands to configure the package. 29 | ./configure $(confflags) 30 | touch configure-stamp 31 | 32 | #Architecture 33 | build: config build-arch build-indep 34 | 35 | build-arch: build-arch-stamp 36 | build-arch-stamp: configure-stamp 37 | # Add here commands to compile the arch part of the package. 38 | #$(MAKE) 39 | touch $@ 40 | 41 | build-indep: build-indep-stamp 42 | build-indep-stamp: configure-stamp 43 | # Add here commands to compile the indep part of the package. 44 | #$(MAKE) doc 45 | touch $@ 46 | 47 | clean: config 48 | dh_testdir 49 | dh_testroot 50 | rm -f build-arch-stamp build-indep-stamp configure-stamp 51 | 52 | # Add here commands to clean up after the build process. 53 | $(MAKE) clean 54 | 55 | dh_clean 56 | 57 | install: install-indep install-arch 58 | install-indep: 59 | dh_testdir 60 | dh_testroot 61 | dh_clean -k -i 62 | dh_installdirs -i 63 | 64 | # Add here commands to install the indep part of the package into 65 | # debian/-doc. 66 | #INSTALLDOC# 67 | 68 | dh_install -i 69 | 70 | install-arch: 71 | dh_testdir 72 | dh_testroot 73 | dh_clean -k -s 74 | dh_installdirs -s 75 | 76 | # Add here commands to install the arch part of the package into 77 | # debian/{package}. 78 | $(MAKE) DESTDIR=$(CURDIR)/debian/sipauthserve install 79 | 80 | dh_install -s 81 | 82 | # Must not depend on anything. This is to be called by 83 | # binary-arch/binary-indep 84 | # in another 'make' thread. 85 | binary-common: 86 | dh_testdir 87 | dh_testroot 88 | # dh_installchangelogs ChangeLog 89 | # dh_installdocs 90 | # dh_installexamples 91 | # dh_installmenu 92 | # dh_installdebconf 93 | dh_installlogrotate 94 | # dh_installemacsen 95 | # dh_installpam 96 | # dh_installmime 97 | # dh_python 98 | dh_installinit --upstart-only --noscripts 99 | # dh_installcron 100 | # dh_installinfo 101 | dh_installman 102 | dh_link 103 | # dh_strip 104 | dh_compress 105 | dh_fixperms 106 | # dh_perl 107 | dh_makeshlibs 108 | dh_installdeb 109 | dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info 110 | dh_gencontrol 111 | dh_md5sums 112 | dh_builddeb 113 | # Build architecture independant packages using the common target. 114 | binary-indep: build-indep install-indep 115 | $(MAKE) -f debian/rules DH_OPTIONS=-i binary-common 116 | 117 | # Build architecture dependant packages using the common target. 118 | binary-arch: build-arch install-arch 119 | $(MAKE) -f debian/rules DH_OPTIONS=-s binary-common 120 | 121 | binary: config binary-arch binary-indep 122 | 123 | .PHONY: build clean binary-indep binary-arch binary install install-indep install-arch config 124 | -------------------------------------------------------------------------------- /debian/sipauthserve.upstart: -------------------------------------------------------------------------------- 1 | # sipauthserve - Range Networks SIP Authorization Server 2 | # 3 | # This service runs sipauthserve from the point the system is 4 | # started until it is shut down again. 5 | 6 | start on stopped rc RUNLEVEL=[2345] 7 | stop on runlevel [!2345] 8 | 9 | respawn 10 | exec /OpenBTS/sipauthserve 11 | -------------------------------------------------------------------------------- /package/after-install-deb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | 18 | set -e 19 | WEBGROUP=www-data 20 | CONFIG_DB='/etc/OpenBTS/sipauthserve.db' 21 | SR_PATH='/var/lib/asterisk/sqlite3dir' 22 | SR_DB='sqlite3.db' 23 | 24 | DATE=$(date +'%Y-%m-%dT%H-%M') # was $(date --rfc-3339='date') 25 | 26 | backup() 27 | { 28 | CONFIG_BACKUP="/etc/OpenBTS/sipauthserve.sql-${DATE}" 29 | if [ -f ${CONFIG_DB} ] && [ ! -e ${CONFIG_BACKUP} ]; then 30 | echo "backing up SAS configuration DB..." 31 | sqlite3 ${CONFIG_DB} ".dump" > ${CONFIG_BACKUP} 32 | echo "done" 33 | fi 34 | 35 | SR_BACKUP="sqlite3.sql-${DATE}" 36 | if [ -f ${SR_PATH}/${SR_DB} ] && [ ! -e ${SR_BACKUP} ]; then 37 | echo "backing up Subscriber Registry DB..." 38 | sqlite3 ${SR_PATH}/${SR_DB} ".dump" > ${SR_PATH}/${SR_BACKUP} 39 | echo "done" 40 | fi 41 | } 42 | 43 | updatedb() { 44 | HASPREPAID=`sqlite3 ${SR_PATH}/${SR_DB} "PRAGMA table_info(sip_buddies)" | grep prepaid || true` 45 | if [ "$HASPREPAID" = "" ]; then 46 | sqlite3 ${SR_PATH}/${SR_DB} "alter table sip_buddies add prepaid int(1) DEFAULT 0 not null" 47 | fi 48 | 49 | HASBALANCE=`sqlite3 ${SR_PATH}/${SR_DB} "PRAGMA table_info(sip_buddies)" | grep account_balance || true` 50 | if [ "$HASBALANCE" = "" ]; then 51 | sqlite3 ${SR_PATH}/${SR_DB} "alter table sip_buddies add column account_balance int(9) default 0" 52 | fi 53 | 54 | sqlite3 ${SR_PATH}/${SR_DB} "create table if not exists rates (service varchar(30) unique not null, rate integer not null)" 55 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('in-network-SMS', 10)" 56 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('out-of-network-SMS', 20)" 57 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('in-network-call', 1)" 58 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('out-of-network-call', 1)" 59 | } 60 | 61 | config() { 62 | # setup configuration db 63 | sqlite3 ${CONFIG_DB} ".read /etc/OpenBTS/sipauthserve.example.sql" > /dev/null 2>&1 64 | 65 | set +e 66 | if [ -e ${SR_PATH}/${SR_DB} ]; then 67 | if [ "$(sqlite3 ${SR_PATH}/${SR_DB} '.tables sip_buddies' | wc -l)" = "1" ]; then 68 | updatedb 69 | else 70 | echo "Unknown Subscriber Registry database format, exiting..." 71 | exit 1 72 | fi 73 | fi 74 | set -e 75 | 76 | chown -R asterisk:${WEBGROUP} ${SR_PATH} 77 | chmod -R ug+rw ${SR_PATH} 78 | chmod -R o-w ${SR_PATH} 79 | } 80 | 81 | backup 82 | config 83 | -------------------------------------------------------------------------------- /package/after-install-rpm.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | 18 | set -e 19 | WEBGROUP=apache 20 | CONFIG_DB='/etc/OpenBTS/sipauthserve.db' 21 | SR_PATH='/var/lib/asterisk/sqlite3dir' 22 | SR_DB='sqlite3.db' 23 | 24 | DATE=$(date +'%Y-%m-%dT%H-%M') # was $(date --rfc-3339='date') 25 | 26 | backup() 27 | { 28 | CONFIG_BACKUP="/etc/OpenBTS/sipauthserve.sql-${DATE}" 29 | if [ -f ${CONFIG_DB} ] && [ ! -e ${CONFIG_BACKUP} ]; then 30 | echo "backing up SAS configuration DB..." 31 | sqlite3 ${CONFIG_DB} ".dump" > ${CONFIG_BACKUP} 32 | echo "done" 33 | fi 34 | 35 | SR_BACKUP="sqlite3.sql-${DATE}" 36 | if [ -f ${SR_PATH}/${SR_DB} ] && [ ! -e ${SR_BACKUP} ]; then 37 | echo "backing up Subscriber Registry DB..." 38 | sqlite3 ${SR_PATH}/${SR_DB} ".dump" > ${SR_PATH}/${SR_BACKUP} 39 | echo "done" 40 | fi 41 | } 42 | 43 | updatedb() { 44 | HASPREPAID=`sqlite3 ${SR_PATH}/${SR_DB} "PRAGMA table_info(sip_buddies)" | grep prepaid || true` 45 | if [ "$HASPREPAID" = "" ]; then 46 | sqlite3 ${SR_PATH}/${SR_DB} "alter table sip_buddies add prepaid int(1) DEFAULT 0 not null" 47 | fi 48 | 49 | HASBALANCE=`sqlite3 ${SR_PATH}/${SR_DB} "PRAGMA table_info(sip_buddies)" | grep account_balance || true` 50 | if [ "$HASBALANCE" = "" ]; then 51 | sqlite3 ${SR_PATH}/${SR_DB} "alter table sip_buddies add column account_balance int(9) default 0" 52 | fi 53 | 54 | sqlite3 ${SR_PATH}/${SR_DB} "create table if not exists rates (service varchar(30) unique not null, rate integer not null)" 55 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('in-network-SMS', 10)" 56 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('out-of-network-SMS', 20)" 57 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('in-network-call', 1)" 58 | sqlite3 ${SR_PATH}/${SR_DB} "insert or ignore into 'rates' values ('out-of-network-call', 1)" 59 | } 60 | 61 | config() { 62 | # setup configuration db 63 | sqlite3 ${CONFIG_DB} ".read /etc/OpenBTS/sipauthserve.example.sql" > /dev/null 2>&1 64 | 65 | set +e 66 | if [ -e ${SR_PATH}/${SR_DB} ]; then 67 | if [ "$(sqlite3 ${SR_PATH}/${SR_DB} '.tables sip_buddies' | wc -l)" = "1" ]; then 68 | updatedb 69 | else 70 | echo "Unknown Subscriber Registry database format, exiting..." 71 | exit 1 72 | fi 73 | fi 74 | set -e 75 | 76 | chown -R asterisk:${WEBGROUP} ${SR_PATH} 77 | chmod -R ug+rw ${SR_PATH} 78 | chmod -R o-w ${SR_PATH} 79 | } 80 | 81 | backup 82 | config 83 | -------------------------------------------------------------------------------- /package/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | 18 | # use this script to build Debian or RPM packages using fpm 19 | 20 | set -e 21 | 22 | BUILDVERSION='5.1-master' 23 | RPMBUILDVERSION='5.1_master' 24 | BUILDITERATION=1 25 | 26 | function usage() { 27 | echo "# usage: $0 [destination]" 28 | echo " where destination = folder where the package will be saved" 29 | exit 1 30 | } 31 | 32 | function get_linux_flavor() { 33 | if [ -f /etc/os-release ] && grep "ID=ubuntu" /etc/os-release &> /dev/null ; then 34 | OS_FLAVOR='ubuntu' 35 | OS_VERSION=`lsb_release -r -s` 36 | fi 37 | if [ -f /etc/centos-release ]; then 38 | OS_FLAVOR='centos' 39 | OS_VERSION=`cat /etc/centos-release | sed 's/^.* release //g' | sed 's/(.*$//g'` 40 | fi 41 | OS_MAJOR=`echo $OS_VERSION | cut -d '.' -f 1` 42 | OS_ARCH=`arch` 43 | } 44 | 45 | 46 | echo == Building SIPAuthServe package 47 | srcrepodir='COMMERCIAL-subscriberRegistry' 48 | builddir='package/tmp' 49 | here=`pwd` 50 | dirname=`basename ${here}` 51 | 52 | # place the resulting package in $packagedir (or simply one folder up if not specified) 53 | if [ -z "$1" ]; then 54 | packagedir='..' 55 | elif [ "$1" == "--help" ]; then 56 | usage 57 | else 58 | packagedir=$1 59 | if [ ! -d "$packagedir" ]; then 60 | echo " $packagedir is not a valid directory. Exiting..." 61 | exit 1 62 | fi 63 | fi 64 | 65 | if [ x$dirname != x$srcrepodir ]; then 66 | echo "cd to $srcrepodir and try again. Exiting..." 67 | exit 1 68 | fi 69 | 70 | echo " # checking your OS flavor:" 71 | get_linux_flavor 72 | case "${OS_FLAVOR}" in 73 | ubuntu) echo " * It is Ubuntu ${OS_VERSION}, ${OS_ARCH}, we are building a Debian package" 74 | ;; 75 | centos) echo " * It is CentOS ${OS_VERSION}, ${OS_ARCH}, we are building an RPM package" 76 | ;; 77 | *) echo "!! Unsupported OS, exiting..." 78 | exit 1 79 | ;; 80 | esac 81 | echo 82 | 83 | echo " # making a home for this build in ${here}/${builddir}:" 84 | rm -rf ${builddir} 85 | mkdir -p ${builddir}/build 86 | mkdir -p ${builddir}/package 87 | cp package/*.sh ${builddir}/package/ 88 | cp package/inputs ${builddir}/package/ 89 | 90 | case "${OS_FLAVOR}" in 91 | ubuntu) mkdir ${builddir}/deb 92 | ;; 93 | centos) mkdir ${builddir}/rpm 94 | ;; 95 | *) exit 1 96 | ;; 97 | esac 98 | echo 99 | 100 | echo " # building the component:" 101 | ./autogen.sh 102 | ./configure 103 | make clean 104 | make 105 | make check 106 | make install DESTDIR=${here}/${builddir}/build 107 | cd ${builddir}/build 108 | mkdir -p var/lib/asterisk/sqlite3dir 109 | mkdir -p OpenBTS 110 | cd OpenBTS 111 | ln -s ../usr/local/sbin/comp128 112 | ln -s ../usr/local/sbin/sipauthserve 113 | cd ${here} 114 | echo 115 | 116 | echo " # creating a package:" 117 | BUILDREPOREV=`git rev-parse --short=10 HEAD` 118 | case "${OS_FLAVOR}" in 119 | ubuntu) fpm -s dir -t deb -n sipauthserve -C ${builddir}/build \ 120 | -p ${packagedir}/sipauthserve_VERSION-sha1.${BUILDREPOREV}_ARCH.deb \ 121 | --description 'Range Networks - SIP Authorization Server' \ 122 | --version ${BUILDVERSION} \ 123 | --iteration ${BUILDITERATION} \ 124 | --deb-ignore-iteration-in-dependencies \ 125 | --category 'comm' \ 126 | --license 'AGPLv3' \ 127 | --vendor 'Range Packager ' \ 128 | --maintainer 'Range Packager ' \ 129 | --url 'http://www.rangenetworks.com' \ 130 | -d 'sqlite3' -d 'libosip2-dev' -d 'libc6' -d 'libzmq3' \ 131 | --deb-build-depends 'build-essential, debhelper (>= 7), libtool, autoconf, pkg-config, libsqlite3-dev, libzmq3-dev' \ 132 | --after-install package/after-install-deb.sh \ 133 | --pre-uninstall package/pre-uninstall.sh \ 134 | --directories 'var/lib/asterisk/sqlite3dir OpenBTS' \ 135 | --deb-upstart ${here}/debian/sipauthserve.upstart \ 136 | --deb-priority 'optional' \ 137 | --workdir ${here}/${builddir}/deb \ 138 | --inputs package/inputs 139 | # --verbose 140 | ;; 141 | centos) 142 | # place the upstart script manually 143 | mkdir -p ${builddir}/build/etc/init 144 | cp ${here}/debian/sipauthserve.upstart ${builddir}/build/etc/init/sipauthserve.conf 145 | # (oley) do not create a symlink in init.d; this is not a common practice on CentOS 6.5 146 | # mkdir -p ${builddir}/build/etc/init.d 147 | # cd ${builddir}/build/etc/init.d 148 | # ln -s /lib/init/upstart-job sipauthserve 149 | # cd ${here} 150 | 151 | # Bump up the iteration if necessary 152 | while [ -f "${packagedir}/sipauthserve_${RPMBUILDVERSION}-sha1.${BUILDREPOREV}-${BUILDITERATION}.${OS_ARCH}.rpm" ]; do 153 | BUILDITERATION=$((BUILDITERATION + 1)) 154 | done 155 | echo "New build iteration: ${BUILDITERATION}" 156 | 157 | fpm -s dir -t rpm -n sipauthserve -C ${builddir}/build \ 158 | -p ${packagedir}/sipauthserve_VERSION-sha1.${BUILDREPOREV}-${BUILDITERATION}.ARCH.rpm \ 159 | --description 'Range Networks - SIP Authorization Server' \ 160 | --version ${BUILDVERSION} \ 161 | --iteration ${BUILDITERATION} \ 162 | --rpm-ignore-iteration-in-dependencies \ 163 | --category 'comm' \ 164 | --license 'AGPLv3' \ 165 | --vendor 'Range Packager ' \ 166 | --maintainer 'Range Packager ' \ 167 | --url 'http://www.rangenetworks.com' \ 168 | -d 'sqlite' -d 'libosip2' -d 'glibc' -d 'zeromq' \ 169 | -d 'rpm-build' -d 'redhat-rpm-config' -d 'libtool' -d 'autoconf' -d 'pkgconfig' -d 'sqlite-devel >= 3' -d 'libosip2-devel' -d 'zeromq-devel' \ 170 | --after-install package/after-install-rpm.sh \ 171 | --pre-uninstall package/pre-uninstall.sh \ 172 | --directories 'var/lib/asterisk/sqlite3dir OpenBTS' \ 173 | --no-rpm-sign \ 174 | --workdir ${here}/${builddir}/rpm \ 175 | --inputs package/inputs \ 176 | etc/init/sipauthserve.conf 177 | # etc/init.d/sipauthserve 178 | # --verbose \ 179 | ;; 180 | *) 181 | ;; 182 | esac 183 | echo 184 | 185 | # echo " # cleaning up:" 186 | # make clean 187 | # echo 188 | 189 | echo "== All done." 190 | -------------------------------------------------------------------------------- /package/inputs: -------------------------------------------------------------------------------- 1 | usr/local/bin/hexmapper 2 | usr/local/bin/syslogextractor 3 | usr/local/sbin/comp128 4 | usr/local/sbin/sipauthserve 5 | etc/OpenBTS/sipauthserve.example.sql 6 | OpenBTS/comp128 7 | OpenBTS/sipauthserve 8 | var/lib/asterisk/sqlite3dir 9 | -------------------------------------------------------------------------------- /package/pre-uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 Range Networks, Inc. 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU Affero General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU Affero General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU Affero General Public License 16 | # along with this program. If not, see . 17 | 18 | set +e 19 | stop sipauthserve 20 | set -e 21 | -------------------------------------------------------------------------------- /regs.gawk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/gawk 2 | 3 | BEGIN { 4 | #print "Success = " success 5 | #print "Failure = " failure 6 | #print "Json = " json 7 | state = 0 # each line represents a different state, this is used for message processing flow 8 | first="true" 9 | if (json == "true") { 10 | print "{" 11 | } else { 12 | printf "%-32s %-9s %-20s\n", "TIME", "ID", "IMSI", "KI" 13 | printf "================================ ========= ====================\n" 14 | } 15 | debugState=0 # set to 1 to debug 16 | line=0 17 | start=systime() 18 | #print "Start @ " start 19 | } 20 | { 21 | ++line 22 | #printf "line %d\r", line 23 | switch (state) { 24 | case 0: # Initial state - this is the state that process the initial select id from sip_buddies line 25 | # We stay in this state until we get a "select id from sip_buddies 26 | # where username= type message 27 | timestamp=$1 28 | query=$0 29 | sub(/^.*SubscriberRegistry.cpp:[0-9]*:/,"",query) 30 | $0 = query 31 | if (debugState != 0) print "Line: " line ", State: " state ", Message: '" query "'" 32 | if (/^sqlLocal: select id from sip_buddies where username = "/) { 33 | imsi = $9 34 | sub(/"/,"",imsi) # leading quote 35 | sub(/"/,"",imsi) # trailing quote 36 | id = "" 37 | ki = "" 38 | state = 1 # Determine if success or failure 39 | } else 40 | { 41 | state = 0 42 | } 43 | break 44 | case 1: # Determine if success or failure 45 | # Result = ### line 46 | # or not found: select id... line 47 | query=$0 48 | sub(/^.*SubscriberRegistry.cpp:[0-9]*:/,"",query) 49 | $0 = query 50 | if (debugState != 0) print "Line: " line ", State: " state ", Message: '" query "'" 51 | if (/^.*not found: select id.*$/) { 52 | #print "Not found" 53 | if (failure == "true") { 54 | if (json == "true") { 55 | printf " " 56 | if (first == "true") { 57 | first = "false" 58 | printf " " 59 | } else { 60 | printf "," 61 | } 62 | printf "{ \"timestamp\": \"%s\", \"id\": \"%s\", \"imsi\": \"%s\" }\n", 63 | timestamp, "NOT FOUND", imsi 64 | } else { 65 | printf "%-32s %-9s %-20s\n", timestamp, "NOT FOUND", imsi 66 | } 67 | } 68 | state=0 69 | } else { 70 | # This should be a "result = " line with an id 71 | #print "We have an entry" 72 | id = $4 73 | state=2 74 | } 75 | break 76 | 77 | 78 | ################################################################ 79 | ################################################################ 80 | ## ## 81 | ## This set of steps is for the case where we found the entry ## 82 | ## ## 83 | ################################################################ 84 | ################################################################ 85 | case 2: # skip the KI query 86 | # select ki from sip_buddies where username = 87 | query=$0 88 | sub(/^.*SubscriberRegistry.cpp:[0-9]*:/,"",query) 89 | $0 = query 90 | if (/^sqlLocal: select ki from sip_buddies where username = "/) { 91 | if (debugState != 0) print "Line: " line ", State: " state ", Message: '" query "'" 92 | # Next state 93 | state=3 94 | } else { 95 | # stay in the state - a spurrious result line 96 | } 97 | break 98 | case 3: # KI result 99 | query=$0 100 | sub(/^.*SubscriberRegistry.cpp:[0-9]*:/,"",query) 101 | $0 = query 102 | if (debugState != 0) print "Line: " line ", State: " state ", Message: '" query "'" 103 | if (/^sqlQuery: result = /) { 104 | ki = $4 105 | #print "Success finished" 106 | if (success == "true") { 107 | if (json == "true") { 108 | printf " " 109 | if (first == "true") { 110 | first = "false" 111 | printf " " 112 | } else { 113 | printf "," 114 | } 115 | printf "{ \"timestamp\": \"%s\", \"id\": %s, \"imsi\": \"%s\" }\n", 116 | timestamp, id, imsi 117 | } else { 118 | printf "%-32s %-9s %-20s\n", timestamp, id, imsi 119 | } 120 | } 121 | state=0 122 | } else { 123 | # stay in the state - a spurrious line 124 | } 125 | break 126 | 127 | 128 | default: 129 | print "Unknown state " state 130 | state=0 131 | break 132 | } 133 | } 134 | END { 135 | end=systime() 136 | #print "End @ " end 137 | if (json == "true") { 138 | print " ,{ \"lines\": " line ", \"Duration\" : " end - start " }" 139 | print "}" 140 | } else 141 | { 142 | print "Lines: " line 143 | print "Duration: " end - start " seconds" 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /regs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This script will extract entries from /var/log/OpenBTS for registrations 4 | # and failed registrations. 5 | 6 | # Usage: regs.sh [-s] [-f] [-j] 7 | # Where -s is entries that succeeded. 8 | # Where -f is entries that failed. 9 | # If neither is given, both are listed. 10 | # Where -j formats output for json 11 | 12 | success="false" 13 | failure="false" 14 | json="false" 15 | #logfile="/var/log/OpenBTS.log" 16 | #logfile="data.txt" 17 | logfile="foo.log" 18 | 19 | while [ "$#" != "0" ] 20 | do 21 | if [ "$1" == "-f" ] 22 | then 23 | failure="true" 24 | elif [ "$1" == "-s" ] 25 | then 26 | success="true" 27 | elif [ "$1" == "-j" ] 28 | then 29 | json="true" 30 | else 31 | echo Invalid parameter $1 32 | exit 1 33 | fi 34 | shift 35 | done 36 | if [ "$success" == "false" ] && [ "$failure" == "false" ] 37 | then 38 | echo None given, setting both 39 | success="true" 40 | failure="true" 41 | else 42 | echo Success $success 43 | echo Failure $failure 44 | fi 45 | #strsip="select id from sip_buddies" 46 | #strki="select ki from sip_buddies" 47 | #strres="sqlQuery: result = " 48 | #egrep "${strsip}|${strki}|${strres}" | \ 49 | 50 | #grep sipauthserve $logfile | grep SubscriberRegistry.cpp | \ 51 | 52 | sed 's/^Jan \(..\) \(..:..:..\) / 2014:01:\1T\2A /g' < $logfile | \ 53 | sed 's/^Feb \(..\) \(..:..:..\) / 2014:02:\1T\2A /g' | \ 54 | sed 's/^Mar \(..\) \(..:..:..\) / 2014:03:\1T\2A /g' | \ 55 | sed 's/^Apr \(..\) \(..:..:..\) / 2014:04:\1T\2A /g' | \ 56 | sed 's/^May \(..\) \(..:..:..\) / 2014:05:\1T\2A /g' | \ 57 | sed 's/^Jun \(..\) \(..:..:..\) / 2014:06:\1T\2A /g' | \ 58 | sed 's/^Jul \(..\) \(..:..:..\) / 2014:07:\1T\2A /g' | \ 59 | sed 's/^Aug \(..\) \(..:..:..\) / 2014:08:\1T\2A /g' | \ 60 | sed 's/^Sep \(..\) \(..:..:..\) / 2014:09:\1T\2A /g' | \ 61 | sed 's/^Oct \(..\) \(..:..:..\) / 2014:10:\1T\2A /g' | \ 62 | sed 's/^Nov \(..\) \(..:..:..\) / 2014:11:\1T\2A /g' | \ 63 | sed 's/^Dec \(..\) \(..:..:..\) / 2014:12:\1T\2A /g' | \ 64 | gawk -f regs.gawk -v success=$success -v failure=$failure -v json=$json 65 | -------------------------------------------------------------------------------- /servershare.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Kestrel Signal Processing, Inc. 3 | * Copyright 2011, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under the terms of the GNU Affero Public License. 6 | * See the COPYING file in the main directory for details. 7 | * 8 | * This use of this software may be subject to additional restrictions. 9 | * See the LEGAL file in the main directory for details. 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU Affero General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Affero General Public License for more details. 20 | 21 | You should have received a copy of the GNU Affero General Public License 22 | along with this program. If not, see . 23 | 24 | */ 25 | 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include "servershare.h" 36 | #include "sqlite3.h" 37 | #include "Logger.h" 38 | #include "SubscriberRegistry.h" 39 | 40 | using namespace std; 41 | 42 | 43 | extern ConfigurationTable gConfig; 44 | 45 | // just using this for the database access 46 | extern SubscriberRegistry gSubscriberRegistry; 47 | 48 | 49 | 50 | ConfigurationKeyMap getConfigurationKeys() 51 | { 52 | ConfigurationKeyMap map; 53 | ConfigurationKey *tmp; 54 | 55 | tmp = new ConfigurationKey("SubscriberRegistry.A3A8","/OpenBTS/comp128", 56 | "", 57 | ConfigurationKey::CUSTOMERWARN, 58 | ConfigurationKey::FILEPATH, 59 | "", 60 | false, 61 | "Path to the program that implements the A3/A8 algorithm." 62 | ); 63 | map[tmp->getName()] = *tmp; 64 | delete tmp; 65 | 66 | tmp = new ConfigurationKey("SubscriberRegistry.db","/var/lib/asterisk/sqlite3dir/sqlite3.db", 67 | "", 68 | ConfigurationKey::CUSTOMERWARN, 69 | ConfigurationKey::FILEPATH, 70 | "", 71 | false, 72 | "The location of the sqlite3 database holding the subscriber registry." 73 | ); 74 | map[tmp->getName()] = *tmp; 75 | delete tmp; 76 | 77 | tmp = new ConfigurationKey("SubscriberRegistry.Port","5064", 78 | "", 79 | ConfigurationKey::CUSTOMERWARN, 80 | ConfigurationKey::PORT, 81 | "", 82 | false, 83 | "Port used by the SIP Authentication Server." 84 | ); 85 | map[tmp->getName()] = *tmp; 86 | delete tmp; 87 | 88 | return map; 89 | } 90 | 91 | string soGenerateIt() 92 | { 93 | ostringstream os; 94 | for (int i = 0; i < 32; i++) { 95 | // if rand() is too slow you can call it fewer times 96 | os << hex << (rand() & 0xf); 97 | } 98 | return os.str(); 99 | } 100 | 101 | // generate a 128' random number 102 | string generateRand(string imsi) 103 | { 104 | string ki = gSubscriberRegistry.imsiGet(imsi, "ki"); 105 | string ret; 106 | if (ki.length() != 0) { 107 | LOG(INFO) << "ki is known"; 108 | // generate and return rand (clear any cached rand or sres) 109 | gSubscriberRegistry.imsiSet(imsi, "rand", "", "sres", ""); 110 | ret = soGenerateIt(); 111 | } else { 112 | string wRand = gSubscriberRegistry.imsiGet(imsi, "rand"); 113 | if (wRand.length() != 0) { 114 | LOG(INFO) << "ki is unknown, rand is cached"; 115 | // return cached rand 116 | ret = wRand; 117 | } else { 118 | LOG(INFO) << "ki is unknown, rand is not cached"; 119 | // generate rand, cache rand, clear sres, and return rand 120 | wRand = soGenerateIt(); 121 | gSubscriberRegistry.imsiSet(imsi, "rand", wRand, "sres", ""); 122 | ret = wRand; 123 | } 124 | } 125 | return ret; 126 | } 127 | 128 | bool strEqual(string a, string b) 129 | { 130 | return 0 == strcasecmp(a.c_str(), b.c_str()); 131 | } 132 | 133 | bool sresEqual(string a, string b) 134 | { 135 | stringstream ss1; 136 | stringstream ss2; 137 | uint32_t sres1 = 0xffffffff; 138 | uint32_t sres2 = 0xffffffff; 139 | 140 | if (a.empty() || b.empty()) 141 | return false; 142 | 143 | ss1 << hex << a; 144 | ss2 << hex << b; 145 | 146 | ss1 >> sres1; 147 | ss2 >> sres2; 148 | 149 | LOG(DEBUG) << "sres1 = " << sres1; 150 | LOG(DEBUG) << "sres2 = " << sres2; 151 | 152 | return (sres1 == sres2); 153 | } 154 | 155 | bool randEqual(string a, string b) 156 | { 157 | uint64_t rand1h = 0; 158 | uint64_t rand1l = 0; 159 | uint64_t rand2h = 0; 160 | uint64_t rand2l = 0; 161 | 162 | if (a.empty() || b.empty()) 163 | return false; 164 | 165 | Utils::stringToUint(a, &rand1h, &rand1l); 166 | Utils::stringToUint(b, &rand2h, &rand2l); 167 | 168 | LOG(DEBUG) << "rand1h = " << rand1h << ", rand1l = " << rand1l; 169 | LOG(DEBUG) << "rand2h = " << rand2h << ", rand2l = " << rand2l; 170 | 171 | return (rand1h == rand2h) && (rand1l == rand2l); 172 | } 173 | 174 | // verify sres given rand and imsi's ki 175 | // may set kc 176 | // may cache sres and rand 177 | bool authenticate(string imsi, string randx, string sres, string *kc) 178 | { 179 | string ki = gSubscriberRegistry.imsiGet(imsi, "ki"); 180 | bool ret; 181 | if (ki.length() == 0) { 182 | // Ki is unknown 183 | string sres2 = gSubscriberRegistry.imsiGet(imsi, "sres"); 184 | if (sres2.length() == 0) { 185 | LOG(INFO) << "ki unknown, no upstream server, sres not cached"; 186 | // first time - cache sres and rand so next time 187 | // correct cell phone will calc same sres from same rand 188 | gSubscriberRegistry.imsiSet(imsi, "sres", sres, "rand", randx); 189 | ret = true; 190 | } else { 191 | LOG(INFO) << "ki unknown, no upstream server, sres cached"; 192 | // check against cached values of rand and sres 193 | string rand2 = gSubscriberRegistry.imsiGet(imsi, "rand"); 194 | // TODO - on success, compute and return kc 195 | LOG(DEBUG) << "comparing " << sres << " to " << sres2 << " and " << randx << " to " << rand2; 196 | ret = sresEqual(sres, sres2) && randEqual(randx, rand2); 197 | } 198 | } else { 199 | LOG(INFO) << "ki known"; 200 | // Ki is known, so do normal authentication 201 | ostringstream os; 202 | // per user value from subscriber registry 203 | string a3a8 = gSubscriberRegistry.imsiGet(imsi, "a3_a8"); 204 | if (a3a8.length() == 0) { 205 | // config value is default 206 | a3a8 = gConfig.getStr("SubscriberRegistry.A3A8"); 207 | } 208 | os << a3a8 << " 0x" << ki << " 0x" << randx; 209 | // must not put ki into the log 210 | // LOG(INFO) << "running " << os.str(); 211 | FILE *f = popen(os.str().c_str(), "r"); 212 | if (f == NULL) { 213 | LOG(CRIT) << "error: popen failed"; 214 | return false; 215 | } 216 | char sres2[26]; 217 | char *str = fgets(sres2, 26, f); 218 | if (str != NULL && strlen(str) == 25) str[24] = 0; 219 | if (str == NULL || strlen(str) != 24) { 220 | LOG(CRIT) << "error: popen result failed"; 221 | return false; 222 | } 223 | int st = pclose(f); 224 | if (st == -1) { 225 | LOG(CRIT) << "error: pclose failed"; 226 | return false; 227 | } 228 | // first 8 chars are SRES; rest are Kc 229 | *kc = sres2+8; 230 | sres2[8] = 0; 231 | LOG(INFO) << "result = " << sres2; 232 | ret = sresEqual(sres, sres2); 233 | } 234 | LOG(INFO) << "returning = " << ret; 235 | return ret; 236 | } 237 | 238 | string join(string separator, vector &strings) 239 | { 240 | string result(""); 241 | vector::iterator it; 242 | for (it = strings.begin(); it != strings.end(); it++) { 243 | if (it != strings.begin()) result.append(separator); 244 | result.append(*it); 245 | } 246 | return result; 247 | } 248 | 249 | void split(char separator, string tosplit, vector *fields) 250 | { 251 | int p = 0; 252 | while (1) { 253 | size_t q = tosplit.find(separator, p); 254 | if (q == string::npos) { 255 | fields->push_back(tosplit.substr(p)); 256 | break; 257 | } 258 | fields->push_back(tosplit.substr(p, q-p)); 259 | p = q+1; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /servershare.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 Kestrel Signal Processing, Inc. 3 | * Copyright 2011, 2014 Range Networks, Inc. 4 | * 5 | * This software is distributed under the terms of the GNU Affero Public License. 6 | * See the COPYING file in the main directory for details. 7 | * 8 | * This use of this software may be subject to additional restrictions. 9 | * See the LEGAL file in the main directory for details. 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU Affero General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU Affero General Public License for more details. 20 | 21 | You should have received a copy of the GNU Affero General Public License 22 | along with this program. If not, see . 23 | 24 | */ 25 | 26 | 27 | #include 28 | #include "sqlite3.h" 29 | 30 | using namespace std; 31 | 32 | /** 33 | Returns all valid configuration keys for the subscriber registry. 34 | */ 35 | ConfigurationKeyMap getConfigurationKeys(); 36 | 37 | /** 38 | Generate a 128-bit random number. 39 | @param imsi imsi of subscriber the random number is for 40 | */ 41 | string generateRand(string imsi); 42 | 43 | /** 44 | Authenticate 45 | @param imsi imsi of subscriber 46 | @param rand random number 47 | @param sres corresponsing sres 48 | */ 49 | bool authenticate(string imsi, string rand, string sres, string *kc); 50 | 51 | /** 52 | Join the strings in strings, separated by separator 53 | @param separator the separator 54 | @param strings the strings to join 55 | */ 56 | string join(string separator, vector &strings); 57 | 58 | /** 59 | Split tosplit into strings in fields, using separator 60 | @param separator the separator to look for 61 | @param tosplit the string to split 62 | @param fields the vector result 63 | */ 64 | void split(char separator, string tosplit, vector *fields); 65 | 66 | /** 67 | Open the database whose name is in the config table 68 | */ 69 | sqlite3 *openDB(); 70 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/Makefile: -------------------------------------------------------------------------------- 1 | TRUNK=../../../ 2 | COM=$(TRUNK)/CommonLibs/trunk/ 3 | SQL=$(TRUNK)/sqlite3/trunk/ 4 | LOCALLIBS=$(COM)/Logger.cpp $(COM)/Timeval.cpp $(COM)/Threads.cpp $(COM)/Sockets.cpp $(COM)/Configuration.cpp $(SQL)/sqlite3util.cpp 5 | LIBS=$(LOCALLIBS) -losipparser2 -losip2 -lc -lpthread -lsqlite3 6 | INCLUDES=-I$(COM) -I$(SQL) 7 | CPPFLAGS=-g -Wall -Wno-deprecated 8 | 9 | test: test.cpp ../SubscriberRegistry.cpp 10 | g++ -o test $(CPPFLAGS) $(INCLUDES) test.cpp ../SubscriberRegistry.cpp $(LIBS) 11 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/output.exp: -------------------------------------------------------------------------------- 1 | Thu Apr 21 20:36:23 PDT 2011 2 | ../SubscriberRegistry.cpp:-0-:addUser: addUser(imsi,clid) 3 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode) values ("imsi","imsi","friend","phones","dynamic","clid","no","gsm","info"); 4 | ../SubscriberRegistry.cpp:-0-:sqlLocal: insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode) values ("imsi","imsi","friend","phones","dynamic","clid","no","gsm","info"); 5 | ../SubscriberRegistry.cpp:-0-:sqlHttp: insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode) values ("imsi","imsi","friend","phones","dynamic","clid","no","gsm","info"); 6 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: insert into dialdata_table (exten, dial) values ("clid","imsi") 7 | ../SubscriberRegistry.cpp:-0-:sqlLocal: insert into dialdata_table (exten, dial) values ("clid","imsi") 8 | ../SubscriberRegistry.cpp:-0-:sqlHttp: insert into dialdata_table (exten, dial) values ("clid","imsi") 9 | ../SubscriberRegistry.cpp:-0-:getCLIDLocal: getCLIDLocal(imsi) 10 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select callerid from sip_buddies where name = "imsi" 11 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = clid 12 | ../SubscriberRegistry.cpp:-0-:getIMSI: getIMSI(clid) 13 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select dial from dialdata_table where exten = "clid" 14 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = imsi 15 | ../SubscriberRegistry.cpp:-0-:getCLIDLocal: getCLIDLocal(imsi_unknown) 16 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select callerid from sip_buddies where name = "imsi_unknown" 17 | ../SubscriberRegistry.cpp:-0-:sqlHttp: select callerid from sip_buddies where name = "imsi_unknown" 18 | ../SubscriberRegistry.cpp:-0-:sqlQuery: not found 19 | ../SubscriberRegistry.cpp:-0-:getRandForAuthentication: getRandForAuthentication(imsi_r1) 20 | ../SubscriberRegistry.cpp:-0-:log: imsi=imsi_r1&req=rand 21 | ../SubscriberRegistry.cpp:-0-:authenticate: authenticate(imsi_a1,rand_a1,sres_a1) 22 | ../SubscriberRegistry.cpp:-0-:log: imsi=imsi_a1&rand=rand_a1&req=auth&sres=sres_a1 23 | test.cpp:-0-:foo: hexh1000 hexh1000 24 | test.cpp:-0-:foo: hexh1001 hexh1001 25 | test.cpp:-0-:foo: hexh1002 hexh1002 26 | test.cpp:-0-:foo: hexh1003 hexh1003 27 | test.cpp:-0-:foo: hexhexhexhexhexhexhexhexhexh1004 hexhexhexhexhexhexhexhexhexh1004 28 | test.cpp:-0-:foo: hexhexhexhexhexhexhexhexhexh1005 hexhexhexhexhexhexhexhexhexh1005 29 | test.cpp:-0-:foo: hexhexhexhexhexhexhexhexhexh1006 hexhexhexhexhexhexhexhexhexh1006 30 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set prepaid = 0 where name = "imsi" 31 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set prepaid = 0 where name = "imsi" 32 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set prepaid = 0 where name = "imsi" 33 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select prepaid from sip_buddies where name = "imsi" 34 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 0 35 | test.cpp:-0-:main: should be false 0 36 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set prepaid = 1 where name = "imsi" 37 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set prepaid = 1 where name = "imsi" 38 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set prepaid = 1 where name = "imsi" 39 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select prepaid from sip_buddies where name = "imsi" 40 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 1 41 | test.cpp:-0-:main: should be true 1 42 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set secondsRemaining = 100 where name = "imsi" 43 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set secondsRemaining = 100 where name = "imsi" 44 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set secondsRemaining = 100 where name = "imsi" 45 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select secondsRemaining from sip_buddies where name = "imsi" 46 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 100 47 | test.cpp:-0-:main: should be 100 100 48 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set secondsRemaining = secondsRemaining + -50 where name = "imsi" 49 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set secondsRemaining = secondsRemaining + -50 where name = "imsi" 50 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set secondsRemaining = secondsRemaining + -50 where name = "imsi" 51 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select secondsRemaining from sip_buddies where name = "imsi" 52 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 50 53 | test.cpp:-0-:main: should be 50 50 54 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set secondsRemaining = secondsRemaining + -100 where name = "imsi" 55 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set secondsRemaining = secondsRemaining + -100 where name = "imsi" 56 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set secondsRemaining = secondsRemaining + -100 where name = "imsi" 57 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select secondsRemaining from sip_buddies where name = "imsi" 58 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = -50 59 | test.cpp:-0-:main: should be 0 0 60 | ../SubscriberRegistry.cpp:-0-:addUser: addUser(imsi,clid) 61 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode) values ("imsi","imsi","friend","phones","dynamic","clid","no","gsm","info"); 62 | ../SubscriberRegistry.cpp:-0-:sqlLocal: insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode) values ("imsi","imsi","friend","phones","dynamic","clid","no","gsm","info"); 63 | ../SubscriberRegistry.cpp:-0-:sqlHttp: insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode) values ("imsi","imsi","friend","phones","dynamic","clid","no","gsm","info"); 64 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 65 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: insert into dialdata_table (exten, dial) values ("clid","imsi") 66 | ../SubscriberRegistry.cpp:-0-:sqlLocal: insert into dialdata_table (exten, dial) values ("clid","imsi") 67 | ../SubscriberRegistry.cpp:-0-:sqlHttp: insert into dialdata_table (exten, dial) values ("clid","imsi") 68 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 69 | ../SubscriberRegistry.cpp:-0-:getCLIDLocal: getCLIDLocal(imsi) 70 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select callerid from sip_buddies where name = "imsi" 71 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = clid 72 | ../SubscriberRegistry.cpp:-0-:getIMSI: getIMSI(clid) 73 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select dial from dialdata_table where exten = "clid" 74 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = imsi 75 | ../SubscriberRegistry.cpp:-0-:getCLIDLocal: getCLIDLocal(imsi_unknown) 76 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select callerid from sip_buddies where name = "imsi_unknown" 77 | ../SubscriberRegistry.cpp:-0-:sqlHttp: select callerid from sip_buddies where name = "imsi_unknown" 78 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 79 | ../SubscriberRegistry.cpp:-0-:sqlQuery: not found 80 | ../SubscriberRegistry.cpp:-0-:getRandForAuthentication: getRandForAuthentication(imsi_r1) 81 | ../SubscriberRegistry.cpp:-0-:log: imsi=imsi_r1&req=rand 82 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 83 | ../SubscriberRegistry.cpp:-0-:authenticate: authenticate(imsi_a1,rand_a1,sres_a1) 84 | ../SubscriberRegistry.cpp:-0-:log: imsi=imsi_a1&rand=rand_a1&req=auth&sres=sres_a1 85 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 86 | test.cpp:-0-:foo: hexh1000 hexh1000 87 | test.cpp:-0-:foo: hexh1001 hexh1001 88 | test.cpp:-0-:foo: hexh1002 hexh1002 89 | test.cpp:-0-:foo: hexh1003 hexh1003 90 | test.cpp:-0-:foo: hexhexhexhexhexhexhexhexhexh1004 hexhexhexhexhexhexhexhexhexh1004 91 | test.cpp:-0-:foo: hexhexhexhexhexhexhexhexhexh1005 hexhexhexhexhexhexhexhexhexh1005 92 | test.cpp:-0-:foo: hexhexhexhexhexhexhexhexhexh1006 hexhexhexhexhexhexhexhexhexh1006 93 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set prepaid = 0 where name = "imsi" 94 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set prepaid = 0 where name = "imsi" 95 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set prepaid = 0 where name = "imsi" 96 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 97 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select prepaid from sip_buddies where name = "imsi" 98 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 0 99 | test.cpp:-0-:main: should be false 0 100 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set prepaid = 1 where name = "imsi" 101 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set prepaid = 1 where name = "imsi" 102 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set prepaid = 1 where name = "imsi" 103 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 104 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select prepaid from sip_buddies where name = "imsi" 105 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 1 106 | test.cpp:-0-:main: should be true 1 107 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set secondsRemaining = 100 where name = "imsi" 108 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set secondsRemaining = 100 where name = "imsi" 109 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set secondsRemaining = 100 where name = "imsi" 110 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 111 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select secondsRemaining from sip_buddies where name = "imsi" 112 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 100 113 | test.cpp:-0-:main: should be 100 100 114 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set secondsRemaining = secondsRemaining + -50 where name = "imsi" 115 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set secondsRemaining = secondsRemaining + -50 where name = "imsi" 116 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set secondsRemaining = secondsRemaining + -50 where name = "imsi" 117 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 118 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select secondsRemaining from sip_buddies where name = "imsi" 119 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = 50 120 | test.cpp:-0-:main: should be 50 50 121 | ../SubscriberRegistry.cpp:-0-:sqlUpdate: update sip_buddies set secondsRemaining = secondsRemaining + -100 where name = "imsi" 122 | ../SubscriberRegistry.cpp:-0-:sqlLocal: update sip_buddies set secondsRemaining = secondsRemaining + -100 where name = "imsi" 123 | ../SubscriberRegistry.cpp:-0-:sqlHttp: update sip_buddies set secondsRemaining = secondsRemaining + -100 where name = "imsi" 124 | ../SubscriberRegistry.cpp:-0-:http: curl -s --data-binary @/tmp/subscriberregistry.1.-PID- testing > /tmp/subscriberregistry.2.-PID- 125 | ../SubscriberRegistry.cpp:-0-:sqlLocal: select secondsRemaining from sip_buddies where name = "imsi" 126 | ../SubscriberRegistry.cpp:-0-:sqlQuery: result = -50 127 | test.cpp:-0-:main: should be 0 0 128 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/runtest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | make test 4 | logger -plocal7.Debug dwb syslog mark 5 | date > output.got 6 | 7 | # first run without a remote http server 8 | rm -f test.db sr.db 9 | sqlite3 test.db < test.db.init1 10 | sqlite3 sr.db < sr.db.init 11 | ./test 12 | 13 | # then run with a remote http server 14 | rm -f test.db sr.db 15 | sqlite3 test.db < test.db.init2 16 | sqlite3 sr.db < sr.db.init 17 | ./test 18 | 19 | ../syslogextractor >> output.got 20 | mv output.got ootput.got 21 | ../hexmapper ootput.got > output.got 22 | diff output.exp output.got 23 | exit 0 24 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/sr.db.init: -------------------------------------------------------------------------------- 1 | create table dialdata_table ( 2 | id INTEGER, 3 | exten VARCHAR(40) NOT NULL DEFAULT '', 4 | dial VARCHAR(128) NOT NULL DEFAULT '', 5 | PRIMARY KEY (id) 6 | ); 7 | 8 | -- INSERT INTO dialdata_table (exten, dial) VALUES ('1000', '1000'); 9 | -- INSERT INTO dialdata_table (exten, dial) VALUES ('1001', '1001'); 10 | 11 | CREATE TABLE 'sip_buddies' 12 | ( 13 | id integer, 14 | name VARCHAR(80) unique not null, 15 | context VARCHAR(80), 16 | callingpres VARCHAR(30) DEFAULT 'allowed_not_screened', 17 | deny VARCHAR(95), 18 | permit VARCHAR(95), 19 | secret VARCHAR(80), 20 | md5secret VARCHAR(80), 21 | remotesecret VARCHAR(250), 22 | transport VARCHAR(10), 23 | host VARCHAR(31) DEFAULT '' not null, 24 | nat VARCHAR(5) DEFAULT 'no' not null, 25 | type VARCHAR(10) DEFAULT 'friend' not null, 26 | accountcode VARCHAR(20), 27 | amaflags VARCHAR(13), 28 | callgroup VARCHAR(10), 29 | callerid VARCHAR(80), 30 | defaultip VARCHAR(40) DEFAULT '0.0.0.0', 31 | dtmfmode VARCHAR(7) DEFAULT 'rfc2833', 32 | fromuser VARCHAR(80), 33 | fromdomain VARCHAR(80), 34 | insecure VARCHAR(4), 35 | language CHAR(2), 36 | mailbox VARCHAR(50), 37 | pickupgroup VARCHAR(10), 38 | qualify CHAR(3), 39 | regexten VARCHAR(80), 40 | rtptimeout CHAR(3), 41 | rtpholdtimeout CHAR(3), 42 | setvar VARCHAR(100), 43 | disallow VARCHAR(100) DEFAULT 'all', 44 | allow VARCHAR(100) DEFAULT 'ulaw' not null, 45 | fullcontact VARCHAR(80), 46 | ipaddr VARCHAR(40), 47 | port int(5) DEFAULT 0, 48 | username VARCHAR(80), 49 | defaultuser VARCHAR(80), 50 | subscribecontext VARCHAR(80), 51 | directmedia VARCHAR(3), 52 | trustrpid VARCHAR(3), 53 | sendrpid VARCHAR(3), 54 | progressinband VARCHAR(5), 55 | promiscredir VARCHAR(3), 56 | useclientcode VARCHAR(3), 57 | callcounter VARCHAR(3), 58 | busylevel int(11), 59 | allowoverlap VARCHAR(3) DEFAULT 'yes', 60 | allowsubscribe VARCHAR(3) DEFAULT 'yes', 61 | allowtransfer VARCHAR(3) DEFAULT 'yes', 62 | ignoresdpversion VARCHAR(3) DEFAULT 'no', 63 | template VARCHAR(100), 64 | videosupport VARCHAR(6) DEFAULT 'no', 65 | maxcallbitrate int(11), 66 | rfc2833compensate VARCHAR(3) DEFAULT 'yes', 67 | 'session-timers' VARCHAR(10) DEFAULT 'accept', 68 | 'session-expires' int(6) DEFAULT 1800, 69 | 'session-minse' int(6) DEFAULT 90, 70 | 'session-refresher' VARCHAR(3) DEFAULT 'uas', 71 | t38pt_usertpsource VARCHAR(3), 72 | outboundproxy VARCHAR(250), 73 | callbackextension VARCHAR(250), 74 | registertrying VARCHAR(3) DEFAULT 'yes', 75 | timert1 int(6) DEFAULT 500, 76 | timerb int(9), 77 | qualifyfreq int(6) DEFAULT 120, 78 | contactpermit VARCHAR(250), 79 | contactdeny VARCHAR(250), 80 | lastms int(11) DEFAULT 0 not null, 81 | regserver VARCHAR(100), 82 | regseconds int(11) DEFAULT 0 not null, 83 | useragent VARCHAR(100), 84 | cancallforward CHAR(3) DEFAULT 'yes' not null, 85 | canreinvite CHAR(3) DEFAULT 'yes' not null, 86 | mask VARCHAR(95), 87 | musiconhold VARCHAR(100), 88 | restrictcid CHAR(3), 89 | calllimit int(5), 90 | ki VARCHAR(32) DEFAULT '' not null, 91 | rand VARCHAR(32) DEFAULT '' not null, 92 | sres VARCHAR(32) DEFAULT '' not null, 93 | prepaid int(1), 94 | secondsRemaining int(11), 95 | primary key(id) 96 | ) 97 | ; 98 | 99 | -- insert into sip_buddies (name,username,type,context,host) values ('1000','1000','friend','phones','dynamic'); 100 | -- insert into sip_buddies (name,username,type,context,host) values ('1001','1001','friend','phones','dynamic'); 101 | -- insert into sip_buddies (name,ipaddr) values ('imsi2','imsi2ipaddr'); 102 | -- insert into sip_buddies (name) values('imsi_r1'); -- rand should generate 103 | -- insert into sip_buddies (name,rand) values('imsi_r2','12345678901234567890123456789012'); -- rand should return this 104 | -- insert into sip_buddies (name,ki) values ('imsi_a1','7f4d7fbff290e20e60466bc7b5b08e4b'); -- auth should calc 105 | -- insert into sip_buddies (name) values ('imsi_a2'); -- auth should save passed rand and sres 106 | -- insert into sip_buddies (name,rand,sres) values ('imsi_a3','123456789012345678901234567890a3','1234567890123456789012a3'); -- auth should verify rand and sres 107 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../SubscriberRegistry.h" 6 | #include "Configuration.h" 7 | #include "Utils.h" 8 | 9 | using namespace std; 10 | 11 | 12 | ConfigurationTable gConfig("test.db"); 13 | 14 | SubscriberRegistry sr; 15 | 16 | void foo(uint32_t n, string s) 17 | { 18 | LOG(INFO) << Utils::uintToString(n) << " " << s; 19 | } 20 | 21 | void foo(string s) 22 | { 23 | uint64_t h; 24 | uint64_t l; 25 | Utils::stringToUint(s, &h, &l); 26 | LOG(INFO) << Utils::uintToString(h, l) << " " << s; 27 | } 28 | 29 | int main(int argc, char **argv) 30 | { 31 | gLogInit("SubscriberRegistryTest",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7); 32 | 33 | // The idea is just to make sure things are connected right. The important code is shared, and tested elsewhere. 34 | 35 | 36 | // add a user 37 | sr.addUser("imsi", "clid"); 38 | // testing mappings of known user 39 | sr.getCLIDLocal("imsi"); 40 | sr.getIMSI("clid"); 41 | // test mapping of unknow user (so it won't be found locally) 42 | sr.getCLIDLocal("imsi_unknown"); 43 | //sr.getRandForAuthentication(false, "imsi_r1"); 44 | //sr.authenticate(false, "imsi_a1","rand_a1","sres_a1"); 45 | 46 | 47 | // but test the conversions 48 | foo(0xffffffff, "ffffffff"); 49 | foo(0x00000000, "00000000"); 50 | foo(0x12345678, "12345678"); 51 | foo(0x9abcdef0, "9abcdef0"); 52 | 53 | foo("ffffffffffffffff0000000000000000"); 54 | foo("0000000000000000ffffffffffffffff"); 55 | foo("0123456789abcdef0123456789abcdef"); 56 | 57 | 58 | // billing testing - not tested elsewhere 59 | 60 | sr.setPrepaid("imsi", false); 61 | bool b; 62 | sr.isPrepaid("imsi", b); 63 | LOG(INFO) << "should be false " << b; 64 | 65 | sr.setPrepaid("imsi", true); 66 | sr.isPrepaid("imsi", b); 67 | LOG(INFO) << "should be true " << b; 68 | 69 | sr.setSeconds("imsi", 100); 70 | int t; 71 | sr.secondsRemaining("imsi", t); 72 | LOG(INFO) << "should be 100 " << t; 73 | 74 | sr.addSeconds("imsi", -50, t); 75 | LOG(INFO) << "should be 50 " << t; 76 | 77 | sr.addSeconds("imsi", -100, t); 78 | LOG(INFO) << "should be 0 " << t; 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/test.db.init1: -------------------------------------------------------------------------------- 1 | BEGIN TRANSACTION; 2 | CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); 3 | INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,''); 4 | INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,''); 5 | INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,''); 6 | COMMIT; 7 | -------------------------------------------------------------------------------- /test.SubscriberRegistry/test.db.init2: -------------------------------------------------------------------------------- 1 | BEGIN TRANSACTION; 2 | CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); 3 | INSERT INTO "CONFIG" VALUES('Log.Level','DEBUG',0,0,''); 4 | INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,''); 5 | INSERT INTO "CONFIG" VALUES('SIP.Proxy.Registration','testing',0,0,''); 6 | COMMIT; 7 | -------------------------------------------------------------------------------- /test.sipauthserve/exit.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | CSeq: 1 REGISTER 9 | Supported: path 10 | Content-Length: 0 11 | -------------------------------------------------------------------------------- /test.sipauthserve/output.exp: -------------------------------------------------------------------------------- 1 | Fri Mar 18 16:47:33 PDT 2011 2 | IMSI12345678901231|||known| 3 | IMSI12345678901232|||| 4 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 5 | IMSI12345678901235|||| 6 | sipauthserve.cpp:-0-:prettyPrint: request: 7 | REGISTER sip:localhost SIP/2.0^M 8 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 9 | From: ;tag=4fa3^M 10 | To: ^M 11 | CSeq: 1 REGISTER^M 12 | Contact: ;expires=600000^M 13 | Max-forwards: 70^M 14 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 15 | Supported: path^M 16 | Content-Length: 0^M 17 | ^M 18 | sipauthserve.cpp:-0-:processBuffer: imsi known, 1st register 19 | servershare.cpp:-0-:generateRand: ki is known 20 | sipauthserve.cpp:-0-:prettyPrint: response: 21 | SIP/2.0 401 Unauthorized^M 22 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 23 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 24 | From: ;tag=4fa3^M 25 | To: ^M 26 | CSeq: 1 REGISTER^M 27 | Contact: ;expires=600000^M 28 | WWW-Authenticate: Digest nonce=hexhexhexhexhexhexhexhexhexh1001^M 29 | Max-forwards: 70^M 30 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 31 | Supported: path^M 32 | Content-Length: 0^M 33 | ^M 34 | sipauthserve.cpp:-0-:processBuffer: 35 | ---------------- 36 | sipauthserve.cpp:-0-:prettyPrint: request: 37 | REGISTER sip:localhost SIP/2.0^M 38 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 39 | From: ;tag=4fa3^M 40 | To: ^M 41 | CSeq: 1 REGISTER^M 42 | Contact: ;expires=600000^M 43 | Max-forwards: 70^M 44 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 45 | Supported: path^M 46 | Content-Length: 0^M 47 | ^M 48 | IMSI12345678901231|||known| 49 | IMSI12345678901232|||| 50 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 51 | IMSI12345678901235|||| 52 | sipauthserve.cpp:-0-:prettyPrint: request: 53 | REGISTER sip:localhost SIP/2.0^M 54 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 55 | From: ;tag=4fa3^M 56 | To: ^M 57 | CSeq: 1 REGISTER^M 58 | Contact: ;expires=600000^M 59 | Max-forwards: 70^M 60 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 61 | Supported: path^M 62 | Content-Length: 0^M 63 | ^M 64 | sipauthserve.cpp:-0-:processBuffer: imsi known, 1st register 65 | servershare.cpp:-0-:generateRand: ki is unknown, rand is not cached 66 | sipauthserve.cpp:-0-:prettyPrint: response: 67 | SIP/2.0 401 Unauthorized^M 68 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 69 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 70 | From: ;tag=4fa3^M 71 | To: ^M 72 | CSeq: 1 REGISTER^M 73 | Contact: ;expires=600000^M 74 | WWW-Authenticate: Digest nonce=hexhexhexhexhexhexhexhexhexh1002^M 75 | Max-forwards: 70^M 76 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 77 | Supported: path^M 78 | Content-Length: 0^M 79 | ^M 80 | sipauthserve.cpp:-0-:processBuffer: 81 | ---------------- 82 | sipauthserve.cpp:-0-:prettyPrint: request: 83 | REGISTER sip:localhost SIP/2.0^M 84 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 85 | From: ;tag=4fa3^M 86 | To: ^M 87 | CSeq: 1 REGISTER^M 88 | Contact: ;expires=600000^M 89 | Max-forwards: 70^M 90 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 91 | Supported: path^M 92 | Content-Length: 0^M 93 | ^M 94 | IMSI12345678901231|||known| 95 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 96 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 97 | IMSI12345678901235|||| 98 | sipauthserve.cpp:-0-:prettyPrint: request: 99 | REGISTER sip:localhost SIP/2.0^M 100 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 101 | From: ;tag=4fa3^M 102 | To: ^M 103 | CSeq: 1 REGISTER^M 104 | Contact: ;expires=600000^M 105 | Max-forwards: 70^M 106 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 107 | Supported: path^M 108 | Content-Length: 0^M 109 | ^M 110 | sipauthserve.cpp:-0-:processBuffer: imsi known, 1st register 111 | servershare.cpp:-0-:generateRand: ki is unknown, rand is cached 112 | sipauthserve.cpp:-0-:prettyPrint: response: 113 | SIP/2.0 401 Unauthorized^M 114 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 115 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 116 | From: ;tag=4fa3^M 117 | To: ^M 118 | CSeq: 1 REGISTER^M 119 | Contact: ;expires=600000^M 120 | WWW-Authenticate: Digest nonce=hexhexhexhexhexhexhexhexhexh1002^M 121 | Max-forwards: 70^M 122 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 123 | Supported: path^M 124 | Content-Length: 0^M 125 | ^M 126 | sipauthserve.cpp:-0-:processBuffer: 127 | ---------------- 128 | sipauthserve.cpp:-0-:prettyPrint: request: 129 | REGISTER sip:localhost SIP/2.0^M 130 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 131 | From: ;tag=4fa3^M 132 | To: ^M 133 | CSeq: 1 REGISTER^M 134 | Contact: ;expires=600000^M 135 | Max-forwards: 70^M 136 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 137 | Supported: path^M 138 | Content-Length: 0^M 139 | ^M 140 | IMSI12345678901231|||known| 141 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 142 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 143 | IMSI12345678901235|||| 144 | sipauthserve.cpp:-0-:prettyPrint: request: 145 | REGISTER sip:localhost SIP/2.0^M 146 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 147 | From: ;tag=4fa3^M 148 | To: ^M 149 | CSeq: 1 REGISTER^M 150 | Contact: ;expires=600000^M 151 | Max-forwards: 70^M 152 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 153 | Supported: path^M 154 | Content-Length: 0^M 155 | ^M 156 | sipauthserve.cpp:-0-:processBuffer: imsi unknown 157 | sipauthserve.cpp:-0-:prettyPrint: response: 158 | SIP/2.0 404 IMSI Not Found^M 159 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 160 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 161 | From: ;tag=4fa3^M 162 | To: ^M 163 | CSeq: 1 REGISTER^M 164 | Contact: ;expires=600000^M 165 | Max-forwards: 70^M 166 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 167 | Supported: path^M 168 | Content-Length: 0^M 169 | ^M 170 | sipauthserve.cpp:-0-:processBuffer: 171 | ---------------- 172 | sipauthserve.cpp:-0-:prettyPrint: request: 173 | REGISTER sip:localhost SIP/2.0^M 174 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 175 | From: ;tag=4fa3^M 176 | To: ^M 177 | CSeq: 1 REGISTER^M 178 | Contact: ;expires=600000^M 179 | Max-forwards: 70^M 180 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 181 | Supported: path^M 182 | Content-Length: 0^M 183 | ^M 184 | IMSI12345678901231|||known| 185 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 186 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 187 | IMSI12345678901235|||| 188 | sipauthserve.cpp:-0-:prettyPrint: request: 189 | REGISTER sip:localhost SIP/2.0^M 190 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 191 | From: ;tag=4fa3^M 192 | To: ^M 193 | CSeq: 1 REGISTER^M 194 | Contact: ;expires=600000^M 195 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 196 | Max-forwards: 70^M 197 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 198 | Supported: path^M 199 | Content-Length: 0^M 200 | ^M 201 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 202 | servershare.cpp:-0-:authenticate: ki known 203 | servershare.cpp:-0-:authenticate: result = hexh1005 204 | servershare.cpp:-0-:authenticate: returning = 1 205 | sipauthserve.cpp:-0-:prettyPrint: response: 206 | SIP/2.0 200 OK^M 207 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 208 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 209 | From: ;tag=4fa3^M 210 | To: ^M 211 | CSeq: 1 REGISTER^M 212 | Contact: ;expires=600000^M 213 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 214 | Max-forwards: 70^M 215 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 216 | Supported: path^M 217 | Content-Length: 0^M 218 | ^M 219 | sipauthserve.cpp:-0-:processBuffer: 220 | ---------------- 221 | sipauthserve.cpp:-0-:prettyPrint: request: 222 | REGISTER sip:localhost SIP/2.0^M 223 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 224 | From: ;tag=4fa3^M 225 | To: ^M 226 | CSeq: 1 REGISTER^M 227 | Contact: ;expires=600000^M 228 | Max-forwards: 70^M 229 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 230 | Supported: path^M 231 | Content-Length: 0^M 232 | ^M 233 | IMSI12345678901231|||known| 234 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 235 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 236 | IMSI12345678901235|||| 237 | sipauthserve.cpp:-0-:prettyPrint: request: 238 | REGISTER sip:localhost SIP/2.0^M 239 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 240 | From: ;tag=4fa3^M 241 | To: ^M 242 | CSeq: 1 REGISTER^M 243 | Contact: ;expires=600000^M 244 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1006", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 245 | Max-forwards: 70^M 246 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 247 | Supported: path^M 248 | Content-Length: 0^M 249 | ^M 250 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 251 | servershare.cpp:-0-:authenticate: ki known 252 | servershare.cpp:-0-:authenticate: result = hexh1007 253 | servershare.cpp:-0-:authenticate: returning = 0 254 | sipauthserve.cpp:-0-:prettyPrint: response: 255 | SIP/2.0 401 Unauthorized^M 256 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 257 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 258 | From: ;tag=4fa3^M 259 | To: ^M 260 | CSeq: 1 REGISTER^M 261 | Contact: ;expires=600000^M 262 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1006", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 263 | Max-forwards: 70^M 264 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 265 | Supported: path^M 266 | Content-Length: 0^M 267 | ^M 268 | sipauthserve.cpp:-0-:processBuffer: 269 | ---------------- 270 | sipauthserve.cpp:-0-:prettyPrint: request: 271 | REGISTER sip:localhost SIP/2.0^M 272 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 273 | From: ;tag=4fa3^M 274 | To: ^M 275 | CSeq: 1 REGISTER^M 276 | Contact: ;expires=600000^M 277 | Max-forwards: 70^M 278 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 279 | Supported: path^M 280 | Content-Length: 0^M 281 | ^M 282 | IMSI12345678901231|||known| 283 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 284 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 285 | IMSI12345678901235|||| 286 | sipauthserve.cpp:-0-:prettyPrint: request: 287 | REGISTER sip:localhost SIP/2.0^M 288 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 289 | From: ;tag=4fa3^M 290 | To: ^M 291 | CSeq: 1 REGISTER^M 292 | Contact: ;expires=600000^M 293 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1008"^M 294 | Max-forwards: 70^M 295 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 296 | Supported: path^M 297 | Content-Length: 0^M 298 | ^M 299 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 300 | servershare.cpp:-0-:authenticate: ki known 301 | servershare.cpp:-0-:authenticate: result = hexh1005 302 | servershare.cpp:-0-:authenticate: returning = 0 303 | sipauthserve.cpp:-0-:prettyPrint: response: 304 | SIP/2.0 401 Unauthorized^M 305 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 306 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 307 | From: ;tag=4fa3^M 308 | To: ^M 309 | CSeq: 1 REGISTER^M 310 | Contact: ;expires=600000^M 311 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1008"^M 312 | Max-forwards: 70^M 313 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 314 | Supported: path^M 315 | Content-Length: 0^M 316 | ^M 317 | sipauthserve.cpp:-0-:processBuffer: 318 | ---------------- 319 | sipauthserve.cpp:-0-:prettyPrint: request: 320 | REGISTER sip:localhost SIP/2.0^M 321 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 322 | From: ;tag=4fa3^M 323 | To: ^M 324 | CSeq: 1 REGISTER^M 325 | Contact: ;expires=600000^M 326 | Max-forwards: 70^M 327 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 328 | Supported: path^M 329 | Content-Length: 0^M 330 | ^M 331 | IMSI12345678901231|||known| 332 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 333 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 334 | IMSI12345678901235|||| 335 | sipauthserve.cpp:-0-:prettyPrint: request: 336 | REGISTER sip:localhost SIP/2.0^M 337 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 338 | From: ;tag=4fa3^M 339 | To: ^M 340 | CSeq: 1 REGISTER^M 341 | Contact: ;expires=600000^M 342 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 343 | Max-forwards: 70^M 344 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 345 | Supported: path^M 346 | Content-Length: 0^M 347 | ^M 348 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 349 | servershare.cpp:-0-:authenticate: ki unknown, no upstream server, sres not cached 350 | servershare.cpp:-0-:authenticate: returning = 1 351 | sipauthserve.cpp:-0-:prettyPrint: response: 352 | SIP/2.0 200 OK^M 353 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 354 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 355 | From: ;tag=4fa3^M 356 | To: ^M 357 | CSeq: 1 REGISTER^M 358 | Contact: ;expires=600000^M 359 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 360 | Max-forwards: 70^M 361 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 362 | Supported: path^M 363 | Content-Length: 0^M 364 | ^M 365 | sipauthserve.cpp:-0-:processBuffer: 366 | ---------------- 367 | sipauthserve.cpp:-0-:prettyPrint: request: 368 | REGISTER sip:localhost SIP/2.0^M 369 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 370 | From: ;tag=4fa3^M 371 | To: ^M 372 | CSeq: 1 REGISTER^M 373 | Contact: ;expires=600000^M 374 | Max-forwards: 70^M 375 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 376 | Supported: path^M 377 | Content-Length: 0^M 378 | ^M 379 | IMSI12345678901231|||known| 380 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 381 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 382 | IMSI12345678901235|hexhexhexhexhexhexhexhexhexh1003|hexh1005|| 383 | sipauthserve.cpp:-0-:prettyPrint: request: 384 | REGISTER sip:localhost SIP/2.0^M 385 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 386 | From: ;tag=4fa3^M 387 | To: ^M 388 | CSeq: 1 REGISTER^M 389 | Contact: ;expires=600000^M 390 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 391 | Max-forwards: 70^M 392 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 393 | Supported: path^M 394 | Content-Length: 0^M 395 | ^M 396 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 397 | servershare.cpp:-0-:authenticate: ki unknown, no upstream server, sres cached 398 | servershare.cpp:-0-:authenticate: returning = 1 399 | sipauthserve.cpp:-0-:prettyPrint: response: 400 | SIP/2.0 200 OK^M 401 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 402 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 403 | From: ;tag=4fa3^M 404 | To: ^M 405 | CSeq: 1 REGISTER^M 406 | Contact: ;expires=600000^M 407 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 408 | Max-forwards: 70^M 409 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 410 | Supported: path^M 411 | Content-Length: 0^M 412 | ^M 413 | sipauthserve.cpp:-0-:processBuffer: 414 | ---------------- 415 | sipauthserve.cpp:-0-:prettyPrint: request: 416 | REGISTER sip:localhost SIP/2.0^M 417 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 418 | From: ;tag=4fa3^M 419 | To: ^M 420 | CSeq: 1 REGISTER^M 421 | Contact: ;expires=600000^M 422 | Max-forwards: 70^M 423 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 424 | Supported: path^M 425 | Content-Length: 0^M 426 | ^M 427 | IMSI12345678901231|||known| 428 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 429 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 430 | IMSI12345678901235|hexhexhexhexhexhexhexhexhexh1003|hexh1005|| 431 | sipauthserve.cpp:-0-:prettyPrint: request: 432 | REGISTER sip:localhost SIP/2.0^M 433 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 434 | From: ;tag=4fa3^M 435 | To: ^M 436 | CSeq: 1 REGISTER^M 437 | Contact: ;expires=600000^M 438 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1006", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 439 | Max-forwards: 70^M 440 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 441 | Supported: path^M 442 | Content-Length: 0^M 443 | ^M 444 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 445 | servershare.cpp:-0-:authenticate: ki unknown, no upstream server, sres cached 446 | servershare.cpp:-0-:authenticate: returning = 0 447 | sipauthserve.cpp:-0-:prettyPrint: response: 448 | SIP/2.0 401 Unauthorized^M 449 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 450 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 451 | From: ;tag=4fa3^M 452 | To: ^M 453 | CSeq: 1 REGISTER^M 454 | Contact: ;expires=600000^M 455 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1006", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1004"^M 456 | Max-forwards: 70^M 457 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 458 | Supported: path^M 459 | Content-Length: 0^M 460 | ^M 461 | sipauthserve.cpp:-0-:processBuffer: 462 | ---------------- 463 | sipauthserve.cpp:-0-:prettyPrint: request: 464 | REGISTER sip:localhost SIP/2.0^M 465 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 466 | From: ;tag=4fa3^M 467 | To: ^M 468 | CSeq: 1 REGISTER^M 469 | Contact: ;expires=600000^M 470 | Max-forwards: 70^M 471 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 472 | Supported: path^M 473 | Content-Length: 0^M 474 | ^M 475 | IMSI12345678901231|||known| 476 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 477 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 478 | IMSI12345678901235|hexhexhexhexhexhexhexhexhexh1003|hexh1005|| 479 | sipauthserve.cpp:-0-:prettyPrint: request: 480 | REGISTER sip:localhost SIP/2.0^M 481 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 482 | From: ;tag=4fa3^M 483 | To: ^M 484 | CSeq: 1 REGISTER^M 485 | Contact: ;expires=600000^M 486 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1008"^M 487 | Max-forwards: 70^M 488 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 489 | Supported: path^M 490 | Content-Length: 0^M 491 | ^M 492 | sipauthserve.cpp:-0-:processBuffer: imsi known, 2nd register 493 | servershare.cpp:-0-:authenticate: ki unknown, no upstream server, sres cached 494 | servershare.cpp:-0-:authenticate: returning = 0 495 | sipauthserve.cpp:-0-:prettyPrint: response: 496 | SIP/2.0 401 Unauthorized^M 497 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 498 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 499 | From: ;tag=4fa3^M 500 | To: ^M 501 | CSeq: 1 REGISTER^M 502 | Contact: ;expires=600000^M 503 | Authorization: Digest, nonce="hexhexhexhexhexhexhexhexhexh1003", uri="sip:IMSI12345678904321", response="hexhexhexhexhexhexhe1008"^M 504 | Max-forwards: 70^M 505 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 506 | Supported: path^M 507 | Content-Length: 0^M 508 | ^M 509 | sipauthserve.cpp:-0-:processBuffer: 510 | ---------------- 511 | sipauthserve.cpp:-0-:prettyPrint: request: 512 | REGISTER sip:localhost SIP/2.0^M 513 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 514 | From: ;tag=4fa3^M 515 | To: ^M 516 | CSeq: 1 REGISTER^M 517 | Contact: ;expires=600000^M 518 | Max-forwards: 70^M 519 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 520 | Supported: path^M 521 | Content-Length: 0^M 522 | ^M 523 | IMSI12345678901231|||known| 524 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 525 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 526 | IMSI12345678901235|hexhexhexhexhexhexhexhexhexh1003|hexh1005|| 527 | sipauthserve.cpp:-0-:prettyPrint: request: 528 | REGISTER sip:localhost SIP/2.0^M 529 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 530 | From: ;tag=4fa3^M 531 | To: ^M 532 | CSeq: 1 REGISTER^M 533 | Contact: ;expires=600000^M 534 | Authorization: Digest, nonce="342abcdef", uri="sip:IMSI12345678904321", response="283742876"^M 535 | Max-forwards: 70^M 536 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 537 | Supported: path^M 538 | Content-Length: 0^M 539 | ^M 540 | sipauthserve.cpp:-0-:processBuffer: imsi unknown 541 | sipauthserve.cpp:-0-:prettyPrint: response: 542 | SIP/2.0 404 IMSI Not Found^M 543 | Via: SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar^M 544 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 545 | From: ;tag=4fa3^M 546 | To: ^M 547 | CSeq: 1 REGISTER^M 548 | Contact: ;expires=600000^M 549 | Authorization: Digest, nonce="342abcdef", uri="sip:IMSI12345678904321", response="283742876"^M 550 | Max-forwards: 70^M 551 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 552 | Supported: path^M 553 | Content-Length: 0^M 554 | ^M 555 | sipauthserve.cpp:-0-:processBuffer: 556 | ---------------- 557 | sipauthserve.cpp:-0-:prettyPrint: request: 558 | REGISTER sip:localhost SIP/2.0^M 559 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd];comp=sigcomp;branch=z9hG4bKnashds7^M 560 | From: ;tag=4fa3^M 561 | To: ^M 562 | CSeq: 1 REGISTER^M 563 | Contact: ;expires=600000^M 564 | Max-forwards: 70^M 565 | P-access-network-info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11^M 566 | Supported: path^M 567 | Content-Length: 0^M 568 | ^M 569 | IMSI12345678901231|||known| 570 | IMSI12345678901232|hexhexhexhexhexhexhexhexhexh1002||| 571 | IMSI12345678901234|||hexhexhexhexhexhexhexhexhexh1000| 572 | IMSI12345678901235|hexhexhexhexhexhexhexhexhexh1003|hexh1005|| 573 | -------------------------------------------------------------------------------- /test.sipauthserve/query.sql: -------------------------------------------------------------------------------- 1 | select name, rand, sres, ki, kc from sip_buddies; 2 | -------------------------------------------------------------------------------- /test.sipauthserve/register1.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | CSeq: 1 REGISTER 9 | Supported: path 10 | Content-Length: 0 11 | -------------------------------------------------------------------------------- /test.sipauthserve/register2.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | CSeq: 1 REGISTER 9 | Supported: path 10 | Content-Length: 0 11 | -------------------------------------------------------------------------------- /test.sipauthserve/register3.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | CSeq: 1 REGISTER 9 | Supported: path 10 | Content-Length: 0 11 | -------------------------------------------------------------------------------- /test.sipauthserve/register4.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="d76fe9a5839089a2ebeb269b46bf46ff", uri="sip:IMSI12345678904321", response="726259AF43D0387D6BDAFC00" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/register4a.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="F76fe9a5839089a2ebeb269b46bf46ff", uri="sip:IMSI12345678904321", response="726259AF43D0387D6BDAFC00" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/register4b.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="d76fe9a5839089a2ebeb269b46bf46ff", uri="sip:IMSI12345678904321", response="F26259AF43D0387D6BDAFC00" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/register5.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="d76fe9a5839089a2ebeb269b46bf46ff", uri="sip:IMSI12345678904321", response="726259AF43D0387D6BDAFC00" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/register5a.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="F76fe9a5839089a2ebeb269b46bf46ff", uri="sip:IMSI12345678904321", response="726259AF43D0387D6BDAFC00" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/register5b.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="d76fe9a5839089a2ebeb269b46bf46ff", uri="sip:IMSI12345678904321", response="F26259AF43D0387D6BDAFC00" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/register6.txt: -------------------------------------------------------------------------------- 1 | REGISTER sip:localhost SIP/2.0 2 | Via: SIP/2.0/UDP [5555::aaa:bbb:ccc:ddd]; comp=sigcomp;branch=z9hG4bKnashds7 3 | Max-Forwards: 70 4 | P-Access-Network-Info: 3GPP-UTRAN-TDD; utran-cell-id-3gpp=234151D0FCE11 5 | From: ;tag=4fa3 6 | To: 7 | Contact: ;expires=600000 8 | Authorization: Digest nonce="342abcdef", uri="sip:IMSI12345678904321", response="283742876" 9 | CSeq: 1 REGISTER 10 | Supported: path 11 | Content-Length: 0 12 | -------------------------------------------------------------------------------- /test.sipauthserve/runtest: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | configdb=/etc/OpenBTS/OpenBTS.db 4 | srdb=sr.db 5 | 6 | # start with a known state in DBs 7 | rm -f $configdb $srdb 8 | # initialize the config db 9 | sqlite3 $configdb < sipauthserve.db.init 10 | # initialize the SR db 11 | sqlite3 $srdb < sr.db.init 12 | chmod 666 $srdb 13 | # initialize the output file 14 | date > output.got 15 | # look at database 16 | sqlite3 $srdb < ./query.sql >> output.got 17 | 18 | # Each test below enters a mark in the syslog so we can extract only 19 | # the log entries for that test. 20 | # Then it starts the sip authentication server. 21 | # Then it sends the test message to the sip authentication server. 22 | # Then it stops the sip authentication server. 23 | # Then it extracts the test's log entries. 24 | # Then it dumps the SR database. 25 | 26 | # rand, imsi known, ki known 27 | logger -plocal7.Debug dwb syslog mark 28 | ../sipauthserve & 29 | ./usender.pl < register1.txt 30 | ./usender.pl < exit.txt 31 | ../syslogextractor >> output.got 32 | sqlite3 $srdb < ./query.sql >> output.got 33 | 34 | # rand, imsi known, ki unknown, rand not cached 35 | logger -plocal7.Debug dwb syslog mark 36 | ../sipauthserve & 37 | ./usender.pl < register2.txt 38 | ./usender.pl < exit.txt 39 | ../syslogextractor >> output.got 40 | sqlite3 $srdb < ./query.sql >> output.got 41 | 42 | # rand, imsi known, ki unknown, rand cached 43 | logger -plocal7.Debug dwb syslog mark 44 | ../sipauthserve & 45 | ./usender.pl < register2.txt 46 | ./usender.pl < exit.txt 47 | ../syslogextractor >> output.got 48 | sqlite3 $srdb < ./query.sql >> output.got 49 | 50 | # rand, imsi unknown 51 | logger -plocal7.Debug dwb syslog mark 52 | ../sipauthserve & 53 | ./usender.pl < register3.txt 54 | ./usender.pl < exit.txt 55 | ../syslogextractor >> output.got 56 | sqlite3 $srdb < ./query.sql >> output.got 57 | 58 | # auth, imsi known, values good 59 | logger -plocal7.Debug dwb syslog mark 60 | ../sipauthserve & 61 | ./usender.pl < register4.txt 62 | ./usender.pl < exit.txt 63 | ../syslogextractor >> output.got 64 | sqlite3 $srdb < ./query.sql >> output.got 65 | 66 | # auth, imsi known, values bad 67 | logger -plocal7.Debug dwb syslog mark 68 | ../sipauthserve & 69 | ./usender.pl < register4a.txt 70 | ./usender.pl < exit.txt 71 | ../syslogextractor >> output.got 72 | sqlite3 $srdb < ./query.sql >> output.got 73 | 74 | # auth, imsi known, values bad 75 | logger -plocal7.Debug dwb syslog mark 76 | ../sipauthserve & 77 | ./usender.pl < register4b.txt 78 | ./usender.pl < exit.txt 79 | ../syslogextractor >> output.got 80 | sqlite3 $srdb < ./query.sql >> output.got 81 | 82 | # auth, imsi known, ki unknown, sres not cached 83 | logger -plocal7.Debug dwb syslog mark 84 | ../sipauthserve & 85 | ./usender.pl < register5.txt 86 | ./usender.pl < exit.txt 87 | ../syslogextractor >> output.got 88 | sqlite3 $srdb < ./query.sql >> output.got 89 | 90 | # auth, imsi known, ki unknown, sres cached, values good 91 | logger -plocal7.Debug dwb syslog mark 92 | ../sipauthserve & 93 | ./usender.pl < register5.txt 94 | ./usender.pl < exit.txt 95 | ../syslogextractor >> output.got 96 | sqlite3 $srdb < ./query.sql >> output.got 97 | 98 | # auth, imsi known, ki unknown, sres cached, values bad 99 | logger -plocal7.Debug dwb syslog mark 100 | ../sipauthserve & 101 | ./usender.pl < register5a.txt 102 | ./usender.pl < exit.txt 103 | ../syslogextractor >> output.got 104 | sqlite3 $srdb < ./query.sql >> output.got 105 | 106 | # auth, imsi known, ki unknown, sres cached, values bad 107 | logger -plocal7.Debug dwb syslog mark 108 | ../sipauthserve & 109 | ./usender.pl < register5b.txt 110 | ./usender.pl < exit.txt 111 | ../syslogextractor >> output.got 112 | sqlite3 $srdb < ./query.sql >> output.got 113 | 114 | # auth, imsi unknown 115 | logger -plocal7.Debug dwb syslog mark 116 | ../sipauthserve & 117 | ./usender.pl < register6.txt 118 | ./usender.pl < exit.txt 119 | ../syslogextractor >> output.got 120 | sqlite3 $srdb < ./query.sql >> output.got 121 | 122 | # normalize the output file for diffing 123 | mv output.got ootput.got 124 | ../hexmapper ootput.got > output.got 125 | diff output.exp output.got 126 | exit 0 127 | -------------------------------------------------------------------------------- /test.sipauthserve/sipauthserve.db.init: -------------------------------------------------------------------------------- 1 | BEGIN TRANSACTION; 2 | CREATE TABLE CONFIG ( KEYSTRING TEXT UNIQUE NOT NULL, VALUESTRING TEXT, STATIC INTEGER DEFAULT 0, OPTIONAL INTEGER DEFAULT 0, COMMENTS TEXT DEFAULT ''); 3 | INSERT INTO "CONFIG" VALUES('SubscriberRegistry.db','sr.db',0,0,'The location of the sqlite3 database holding the subscriber registry.'); 4 | INSERT INTO "CONFIG" VALUES('SubscriberRegistry.A3A8','../comp128',0,0,''); 5 | INSERT INTO "CONFIG" VALUES('Log.Level','INFO',0,0,''); 6 | INSERT INTO "CONFIG" VALUES('Log.Level.smcommands.cpp','INFO',0,0,''); 7 | INSERT INTO "CONFIG" VALUES('savefile','savedqueue.txt',0,0,''); 8 | INSERT INTO "CONFIG" VALUES('SIP.myPort','5063',0,0,''); 9 | INSERT INTO "CONFIG" VALUES('Debug.print_as_we_validate','',0,0,''); 10 | INSERT INTO "CONFIG" VALUES('$optional','Debug.print_as_we_validate',0,0,''); 11 | INSERT INTO "CONFIG" VALUES('BounceMessage.IMSILookupFailed','Cannot determine return address; bouncing message. Text your phone number to 101 to register and try again.',0,0,''); 12 | INSERT INTO "CONFIG" VALUES('BounceMessage.NotRegistered','Phone not registered here.',0,0,''); 13 | INSERT INTO "CONFIG" VALUES('SC.Register.Code','101',0,0,''); 14 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.WelcomeA','Hello',0,0,''); 15 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.WelcomeB','! Text to 411 for system status.',0,0,''); 16 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.AlreadyA','Your phone is already registered as',0,0,''); 17 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.AlreadyB','.',0,0,''); 18 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.TakenA','The phone number',0,0,''); 19 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.TakenB','is already in use. Try another, then call that one to talk to whoever took yours.',0,0,''); 20 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.ErrorA','Error in assigning',0,0,''); 21 | INSERT INTO "CONFIG" VALUES('SC.Register.Msg.ErrorB','to IMSI',0,0,''); 22 | INSERT INTO "CONFIG" VALUES('SC.Register.Digits.Max','10',0,0,''); 23 | INSERT INTO "CONFIG" VALUES('SC.Register.Digits.Min','7',0,0,''); 24 | INSERT INTO "CONFIG" VALUES('SC.Register.Digits.Override','',0,0,''); 25 | INSERT INTO "CONFIG" VALUES('SC.Info.Code','411',0,0,''); 26 | INSERT INTO "CONFIG" VALUES('SC.DebugDump.Code','2336',0,0,''); 27 | INSERT INTO "CONFIG" VALUES('SC.QuickChk.Code','2337',0,0,''); 28 | INSERT INTO "CONFIG" VALUES('SC.ZapQueued.Code','2338',0,0,''); 29 | INSERT INTO "CONFIG" VALUES('SC.ZapQueued.Password','6000',0,0,''); 30 | INSERT INTO "CONFIG" VALUES('SC.WhiplashQuit.Code','314158',0,0,''); 31 | INSERT INTO "CONFIG" VALUES('SC.WhiplashQuit.Password','Snidely',0,0,''); 32 | INSERT INTO "CONFIG" VALUES('SC.WhiplashQuit.SaveFile','testsave.txt',0,0,''); 33 | COMMIT; 34 | -------------------------------------------------------------------------------- /test.sipauthserve/sr.db.init: -------------------------------------------------------------------------------- 1 | BEGIN TRANSACTION; 2 | CREATE TABLE dialdata_table ( 3 | id INTEGER, 4 | exten VARCHAR(40) NOT NULL DEFAULT '', 5 | dial VARCHAR(128) NOT NULL DEFAULT '', 6 | PRIMARY KEY (id) 7 | ); 8 | INSERT INTO "dialdata_table" VALUES(1,'1000','1000'); 9 | INSERT INTO "dialdata_table" VALUES(2,'1001','1001'); 10 | INSERT INTO "dialdata_table" VALUES(3,'clid1','imsi1'); 11 | CREATE TABLE 'sip_buddies' 12 | ( 13 | id integer, 14 | name VARCHAR(80) unique not null, 15 | context VARCHAR(80), 16 | callingpres VARCHAR(30) DEFAULT 'allowed_not_screened', 17 | deny VARCHAR(95), 18 | permit VARCHAR(95), 19 | secret VARCHAR(80), 20 | md5secret VARCHAR(80), 21 | remotesecret VARCHAR(250), 22 | transport VARCHAR(10), 23 | host VARCHAR(31) DEFAULT '' not null, 24 | nat VARCHAR(5) DEFAULT 'no' not null, 25 | type VARCHAR(10) DEFAULT 'friend' not null, 26 | accountcode VARCHAR(20), 27 | amaflags VARCHAR(13), 28 | callgroup VARCHAR(10), 29 | callerid VARCHAR(80), 30 | defaultip VARCHAR(40) DEFAULT '0.0.0.0', 31 | dtmfmode VARCHAR(7) DEFAULT 'rfc2833', 32 | fromuser VARCHAR(80), 33 | fromdomain VARCHAR(80), 34 | insecure VARCHAR(4), 35 | language CHAR(2), 36 | mailbox VARCHAR(50), 37 | pickupgroup VARCHAR(10), 38 | qualify CHAR(3), 39 | regexten VARCHAR(80), 40 | rtptimeout CHAR(3), 41 | rtpholdtimeout CHAR(3), 42 | setvar VARCHAR(100), 43 | disallow VARCHAR(100) DEFAULT 'all', 44 | allow VARCHAR(100) DEFAULT 'ulaw' not null, 45 | fullcontact VARCHAR(80), 46 | ipaddr VARCHAR(40), 47 | port int(5) DEFAULT 0, 48 | username VARCHAR(80), 49 | defaultuser VARCHAR(80), 50 | subscribecontext VARCHAR(80), 51 | directmedia VARCHAR(3), 52 | trustrpid VARCHAR(3), 53 | sendrpid VARCHAR(3), 54 | progressinband VARCHAR(5), 55 | promiscredir VARCHAR(3), 56 | useclientcode VARCHAR(3), 57 | callcounter VARCHAR(3), 58 | busylevel int(11), 59 | allowoverlap VARCHAR(3) DEFAULT 'yes', 60 | allowsubscribe VARCHAR(3) DEFAULT 'yes', 61 | allowtransfer VARCHAR(3) DEFAULT 'yes', 62 | ignoresdpversion VARCHAR(3) DEFAULT 'no', 63 | template VARCHAR(100), 64 | videosupport VARCHAR(6) DEFAULT 'no', 65 | maxcallbitrate int(11), 66 | rfc2833compensate VARCHAR(3) DEFAULT 'yes', 67 | 'session-timers' VARCHAR(10) DEFAULT 'accept', 68 | 'session-expires' int(6) DEFAULT 1800, 69 | 'session-minse' int(6) DEFAULT 90, 70 | 'session-refresher' VARCHAR(3) DEFAULT 'uas', 71 | t38pt_usertpsource VARCHAR(3), 72 | outboundproxy VARCHAR(250), 73 | callbackextension VARCHAR(250), 74 | registertrying VARCHAR(3) DEFAULT 'yes', 75 | timert1 int(6) DEFAULT 500, 76 | timerb int(9), 77 | qualifyfreq int(6) DEFAULT 120, 78 | contactpermit VARCHAR(250), 79 | contactdeny VARCHAR(250), 80 | lastms int(11) DEFAULT 0 not null, 81 | regserver VARCHAR(100), 82 | regseconds int(11) DEFAULT 0 not null, 83 | useragent VARCHAR(100), 84 | cancallforward CHAR(3) DEFAULT 'yes' not null, 85 | canreinvite CHAR(3) DEFAULT 'yes' not null, 86 | mask VARCHAR(95), 87 | musiconhold VARCHAR(100), 88 | restrictcid CHAR(3), 89 | calllimit int(5), 90 | rand varchar(33) default '', 91 | sres varchar(33) default '', 92 | ki varchar(33) default '', 93 | kc varchar(33) default '', 94 | primary key(id) 95 | ); 96 | 97 | insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901231','','','known',''); 98 | insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901232','','','',''); 99 | insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901234','','','48091124c1155bd95c6f1860dc66ce92',''); 100 | insert into sip_buddies (name,rand,sres,ki,kc) values ('IMSI12345678901235','','','',''); 101 | 102 | COMMIT; 103 | -------------------------------------------------------------------------------- /test.sipauthserve/usender.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | $|++; 4 | use strict; 5 | use IO::Socket; 6 | 7 | my($host) = '127.0.0.1'; 8 | my($port) = '5063'; 9 | 10 | my($datagram) = ""; 11 | while (<>) { 12 | $datagram .= $_; 13 | } 14 | my $message = IO::Socket::INET->new(Proto=>"udp", 15 | PeerPort=>$port,PeerAddr=>$host) 16 | or die "Can't make UDP socket ($host:$port): $@"; 17 | # printf "sending $datagram"; 18 | $message->send($datagram); 19 | 20 | 21 | # MESSAGE sip:user2@domain.com SIP/2.0 22 | # Via: SIP/2.0/TCP user1pc.domain.com;branch=z9hG4bK776sgdkse 23 | # Max-Forwards: 70 24 | # From: sip:user1@domain.com;tag=49583 25 | # To: sip:user2@domain.com 26 | # Call-ID: asd88asd77a@1.2.3.4 27 | # CSeq: 1 MESSAGE 28 | # Content-Type: text/plain 29 | # Content-Length: 18 30 | # 31 | # Watson, come here. 32 | --------------------------------------------------------------------------------