[BlueOnyx:13408] Re: CCED Reverse Engineering - API

Michael Stauber mstauber at blueonyx.it
Wed Jul 24 10:13:10 -05 2013


Hi Marcello,

> with the pubblication of API for BO boxes I've started the integration
> with our CRM. They works fine and it's a great work!

Very well.

> I've tried to analyze the php code but I stopped myself when I found
> 
> $cceClient->create
> 
> method. Reading CceClient.php it says
> 
>   // description: create a CCE object of type $class, with properties in
> $vars
>   // returns: oid of created object, or 0 on failure
>   // usage: $oid = $cce->create($class, array( 'property' => 'value' ));
>   function create($class, $vars = array()) {
>     return ccephp_create($this->handle, $class, $vars);
>   }
> 
> I don't know what classes are supported so I've tried to go deeper and
> find the definition of ccephp_create function with no success.
> 
> Is there a way to find the definition of this function or a doc where we
> can find supported classes and specs about array to be passed in $vars?

There is a really easy way to see which Classes are supported on a BlueOnyx:

Fire up "cceclient" on the command line from SSH:

[root at sol ~]# /usr/sausalito/bin/cceclient
100 CSCP/0.80
200 READY

Type "help" to see a list of available commands. But what you really
want to do is to simply type "classes" to get a list of all available
Classes.

classes
110 CLASS FtpSite
110 CLASS pam_abl_settings
110 CLASS Vsite
110 CLASS VsiteServices
110 CLASS WebApplications
110 CLASS EmailAlias
110 CLASS CapabilityGroup
110 CLASS VirtualHost
110 CLASS SOL_Console
110 CLASS MYSQL_DBs
110 CLASS SWUpdateServer
110 CLASS ProtectedEmailAlias
110 CLASS DnsSOA
110 CLASS Network
110 CLASS PHP
110 CLASS Package
110 CLASS JavaWar
110 CLASS MySQL
110 CLASS UserServices
110 CLASS Capabilities
110 CLASS User
110 CLASS Disk
110 CLASS fail_users
110 CLASS DnsSlaveZone
110 CLASS dnsbl
110 CLASS MailList
110 CLASS Schedule
110 CLASS Subdomains
110 CLASS ServiceQuota
110 CLASS IPPoolingRange
110 CLASS ActiveMonitor
110 CLASS DnsRecord
110 CLASS fail_hosts
110 CLASS Workgroup
110 CLASS System
110 CLASS mx2
110 CLASS Route

The Classes themselves are defined in XML Schema files. For this check
the directory /usr/sausalito/schemas/ and its subdirectories. On CCEd
startup the contends of /usr/sausalito/schemas/ are read in and all
valid XML files from within are used to define the Classes.

To find all objects of a certain Class you can type "find Vsite" and it
will provide you with a list of Object IDs of all Classes of that type.

Now here is a really simple Schema for the new API Namespace I created.
A Namespace can extend an existing Class with additional elements.

/usr/sausalito/schemas/base/api/api.schema

<class name="System" namespace="API" version="1.0"
  createacl="ruleAll" destroyacl="ruleAll">

  <property name="enabled" type="boolean"
    optional="true" default="0"
    writeacl="ruleCapable(adminUser)"/>

  <property name="forceHTTPS" type="boolean"
    optional="true" default="1"
    writeacl="ruleCapable(adminUser)"/>

  <property name="apiHosts" type="ipaddr"
    array="yes" optional="true" default=""
    writeacl="ruleCapable(adminUser)"/>

</class>

This extends the "System" Class with the new Namespace "API".

That Namespace then has three Properties:

1.) "enabled", type "boolean", which may be optional and has the default
value of "0".

2.) "forceHTTPS" of type "boolean", which may be optional and has the
default value of "1".

3.) "apiHosts" which takes values of type "ipaddr". It can contain an
array of of ip-adresses and is optional. Default value is that it's empty.

In these Schema files you can define not only if this is a separate and
new Class, but you can also extend Classes with additional Namespaces.
You can define who has access to the information. Such as read access,
write access or access to create or destroy such Objects and Namespaces.
But you can also define which type of information a Property within a
Class or Namespace will store. Which provides for very simple yet
efficient input validation to make sure that nobody writes stuff into
the backend which doesn't make sense or which might contain malicious code.

Now the "type" of information that a property value might have (like
"ipaddr", "boolean", "int", "alphanum_plus" and others) are defined in
Schema files as well.  Most of them are defined in
/usr/sausalito/schemas/basetypes.schema, but some more exotic ones are
defined in other Schema files of individual modules.

For example, here is the rule that defines "alphanum_plus":

<typedef
	name="alphanum_plus"
	type="re"
	data="^[A-Za-z0-9\\._-]+$"
/>

If a property is defined to take only "alphanum_plus" values, then the
above regular expression will be used to verify the input when you try
to use a "create" or "set" action to populate that property. If the
verification goes through without error, the data is saved. If the input
you're trying to submit doesn't match the regular expression, then CCE
will refuse to perform the transaction and you get an error message like
"The field XYZ only takes values that are alphanum_plus."

Now to check this example API Namespace from "cceclient" you need to
first find the "System" object like this:

find system

It reports back an object number. Like "1". To "get" that API object
you'd then type:

get 1 . API

Which will return the contends of the Object or Namespace:

102 DATA NAMESPACE = "API"
102 DATA apiHosts = ""
102 DATA CLASSVER = "1.0"
102 DATA enabled = "1"
102 DATA forceHTTPS = "1"

To "set" the object you'd work in a similar fashion:

set 1 . API enabled = "0"

The schema files are a good source of understanding the data structure
of Objects. But in practical terms you usually use "cceclient" to just
examine an existing object to see what key/value pairs it contains.

You do NOT have to set all key/value pairs during a SET or CREATE
transaction. You can do that, but usually you just set the ones that you
need to have changed or updated. CCE will just leave the rest unchanged
during a SET transaction. During a CREATE transaction it'll create any
properties you omitted with the default values that are defined in the
Schema file of that Object or Namespace.

FWIW: To get a quick glance at all the supported "typedefs" check out
the BlueOnyx 5200R demo:

URL: http://demo.blueonyx.it:444/login
Username: admin
Passsword: demo123

Login there and then look at the sourcecode of any page. Which one
doesn't matter.

In the header of any page you find this:
<script src="/gui/validation?update"></script>

Look at the sources for that. Among a lot of code it has two sections
which might be of interest. One is a brief list of all "typedefs":

		word: {word: true},
		alphanum: {alphanum: true},
		memdisk: {memdisk: true},
		alphanum_plus: {alphanum_plus: true},
		int: {int: true},
		uint: {uint: true},
		boolean: {boolean: true},
		ipaddr: {ipaddr: true},
		email_address: {email_address: true},
		NetAddress: {NetAddress: true},
		netmask: {netmask: true},
		fqdn: {fqdn: true},
		hostname: {hostname: true},
		domainname: {domainname: true},
		password: {password: true},
		cgiAccess: {cgiAccess: true},
		vhostDocRoot: {vhostDocRoot: true},
		emailQueueTime: {emailQueueTime: true},
		mail_alias: {mail_alias: true},
		fq_email_address: {fq_email_address: true},
		schedule_type: {schedule_type: true},
		schedule_filename_type: {schedule_filename_type: true},
		dns_record_type: {dns_record_type: true},
		dns_email: {dns_email: true},
		dns_zone_format: {dns_zone_format: true},
		mx_priority: {mx_priority: true},
		fullName: {fullName: true},
		userNameGenMode: {userNameGenMode: true},
		amstate: {amstate: true},
		statsReport: {statsReport: true},
		swidType: {swidType: true},
		versionType: {versionType: true},
		installStateMode: {installStateMode: true},
		pType: {pType: true},
		uType: {uType: true},
		intervalType: {intervalType: true},
		status: {status: true},
		notifyType: {notifyType: true},
		bootproto: {bootproto: true},
		internetMode: {internetMode: true},
		interface: {interface: true},
		devicename: {devicename: true},
		accountname: {accountname: true},
		knownFs: {knownFs: true},
		diskDevice: {diskDevice: true},
		wakemode: {wakemode: true},
		powermode: {powermode: true},
		telnetaccess: {telnetaccess: true},
		sslCountry: {sslCountry: true},
		postPolicy: {postPolicy: true},
		subPolicy: {subPolicy: true},
		mailman_name: {mailman_name: true}

The other one has the locations of the "typedef" Schema files and the
regular rexpressions that are used:

// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
scalar: function(value, element) {
	return this.optional(element) || /^.*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
word: function(value, element) {
	return this.optional(element) || /^[^ \t\n\r\v\f]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
alphanum: function(value, element) {
	return this.optional(element) || /^[A-Za-z0-9]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
memdisk: function(value, element) {
	return this.optional(element) ||
/^([0-9]{1,9})((K)||(KB)||(M)||(MB)||(G)||(GB)||(T)||(TB))+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
alphanum_plus: function(value, element) {
	return this.optional(element) || /^[A-Za-z0-9\._-]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
alphanum_plus_multiline: function(value, element) {
	return this.optional(element) ||
/^([A-Za-z0-9\._-]{2,})(([,]|[\r\n])[A-Za-z0-9\._-]{2,})*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
int: function(value, element) {
	return this.optional(element) || /^((\-?[1-9][0-9]*)|0)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
uint: function(value, element) {
	return this.optional(element) || /^(([1-9][0-9]*)|0)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
boolean: function(value, element) {
	return this.optional(element) || /^(0|1)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
ipaddr: function(value, element) {
	return this.optional(element) ||
/^(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])\.(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])\.(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])\.(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
email_address: function(value, element) {
	return this.optional(element) ||
/^[a-zA-Z0-9\._-]+\@[a-zA-Z0-9\._-]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
email_addresses: function(value, element) {
	return this.optional(element) ||
/^(.+@[^\.].*\.[a-z]{2,})(([,]|[\r\n]).+@[^\.].*\.[a-z]{2,})*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
NetAddress: function(value, element) {
	return this.optional(element) ||
/(^[A-Za-z0-9][A-Za-z0-9\-]*([\.][A-Za-z0-9][A-Za-z0-9\-]*)*$)|(^([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]+$)|(^(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])\.(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])\.(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])\.(([0-9])|([1-9][0-9])|(1[0-9][0-9])|2[0-4][0-9]|25[0-5])$)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
NetAddresses: function(value, element) {
	return this.optional(element) || /^(.*)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
netmask: function(value, element) {
	return this.optional(element) ||
/^(([1-9])|([12][0-9])|(3[0-2])|((0|128|192|224|240|248|252|254|255)\.0\.0\.0)|255\.((0|128|192|224|240|248|252|254|255)\.0\.0)|255\.255\.((0|128|192|224|240|248|252|254|255)\.0)|255\.255\.255\.((0|128|192|224|240|248|252|254|255)))$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
fqdn: function(value, element) {
	return this.optional(element) ||
/(?=^.{1,254}$)(^(?:(?!\d+\.)[a-zA-Z0-9_\-]{1,63}\.?)+(?:[a-zA-Z]{2,})$)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
hostname: function(value, element) {
	return this.optional(element) ||
/^[A-Za-z0-9][A-Za-z0-9\-]*(\.[A-Za-z0-9][A-Za-z0-9\-]*)*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
domainname: function(value, element) {
	return this.optional(element) ||
/^[A-Za-z0-9][A-Za-z0-9\-]*([\.][A-Za-z0-9][A-Za-z0-9\-]*)*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
domainnames: function(value, element) {
	return this.optional(element) ||
/(([a-zA-Z0-9](-*[a-zA-Z0-9]+)*(\.[a-zA-Z0-9](-*[a-zA-Z0-9]+)*)+)([,]|[\r\n]{0,1}))/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/basetypes.schema
password: function(value, element) {
	return this.optional(element) || /^[^\001-\037\177]{6,24}$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/apache/apache.schema
cgiAccess: function(value, element) {
	return this.optional(element) || /(all|subset|none)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/apache/apache.schema
vhostDocRoot: function(value, element) {
	return this.optional(element) || /^\/.*/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/email/email.schema
emailQueueTime: function(value, element) {
	return this.optional(element) ||
/(immediate|quarter-hourly|half-hourly|hourly|quarter-daily|daily)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/email/email.schema
mail_alias: function(value, element) {
	return this.optional(element) || /^[a-z0-9_\-][a-z0-9_\.\-]*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/email/email.schema
fq_email_address: function(value, element) {
	return this.optional(element) ||
/^[a-zA-Z0-9\._-]+\@[a-zA-Z0-9\._-]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/schedule/schedule.schema
schedule_type: function(value, element) {
	return this.optional(element) ||
/[nN][oO][nN][eE]|[mM][iI][nN][uU][tT][eE]|[qQ][uU][aA][rR][tT][eE][rR]-[hH][oO][uU][rR][lL][yY]|[hH][oO][uU][rR][lL][yY]|[qQ][uU][aA][rR][tT][eE][rR]-[dD][aA][iI][lL][yY]|[dD][aA][iI][lL][yY]|[wW][eE][eE][kK][lL][yY]|[mM][oO][nN][tT][hH][lL][yY]/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/schedule/schedule.schema
schedule_filename_type: function(value, element) {
	return this.optional(element) || /^$|schedule_....../.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/dns/dns.schema
dns_record_type: function(value, element) {
	return this.optional(element) ||
/^(A|PTR|CNAME|MX|TXT|NS|SN)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/dns/dns.schema
dns_email: function(value, element) {
	return this.optional(element) ||
/^[a-zA-Z0-9_-]+\@[a-zA-Z0-9\._-]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/dns/dns.schema
dns_zone_format: function(value, element) {
	return this.optional(element) ||
/^(RFC2317|DION|OCN-JT|USER)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/dns/dns.schema
mx_priority: function(value, element) {
	return this.optional(element) ||
/^(very_high|high|low|very_low)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/user/user.schema
fullName: function(value, element) {
	return this.optional(element) || /^[^:\n\r]*$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/user/user.schema
userNameGenMode: function(value, element) {
	return this.optional(element) ||
/^(firstInitLast|firstLastInit|first|last)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/am/am.schema
amstate: function(value, element) {
	return this.optional(element) || /[NGYR]/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/sitestats/sitestats.schema
statsReport: function(value, element) {
	return this.optional(element) || /(net|web|mail|ftp)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
swidType: function(value, element) {
	return this.optional(element) || /^[A-z0-9+_]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
versionType: function(value, element) {
	return this.optional(element) ||
/(^v([[0-9]{1,4}\.]{0,4}){0,3}[0-9]{1,3}[a-zA-Z]{0,1}$)|(^v([[0-9]{1,4}\.]{0,4}){0,3}[0-9]{1,4}[a-zA-Z]{0,1}-[a-zA-Z0-9]{1,8}$)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
installStateMode: function(value, element) {
	return this.optional(element) || /^(Available|Installed)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
pType: function(value, element) {
	return this.optional(element) || /^(update|complete)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
uType: function(value, element) {
	return this.optional(element) || /^(Updates|All)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
intervalType: function(value, element) {
	return this.optional(element) ||
/^(Never|Hourly|Daily|Weekly|Monthly)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
status: function(value, element) {
	return this.optional(element) || /(up|down)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/swupdate/update.schema
notifyType: function(value, element) {
	return this.optional(element) || /^(AllNew|UpdatesOnly)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/network/network.schema
bootproto: function(value, element) {
	return this.optional(element) || /^(dhcp|none)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/network/network.schema
internetMode: function(value, element) {
	return this.optional(element) ||
/^(none|broadband|lan|narrowband)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/network/network.schema
interface: function(value, element) {
	return this.optional(element) ||
/(^eth[0-9]+(:[0-9]+)?$)|(^venet[0-9]+(:[0-9]+)?$)/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/sauce-basic/basic.schema
devicename: function(value, element) {
	return this.optional(element) || /^[A-Za-z0-9]+$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/sauce-basic/basic.schema
accountname: function(value, element) {
	return this.optional(element) || /^[a-z][a-z0-9_.-]{0,30}$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/disk/disk.schema
knownFs: function(value, element) {
	return this.optional(element) ||
/^(ext2|xfs|reiserfs|smbfs|nfs|iso9660)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/disk/disk.schema
diskDevice: function(value, element) {
	return this.optional(element) ||
/^(\/dev\/[A-Za-z0-9]+|[A-Za-z0-9][A-Za-z0-9\-]*(\.[A-Za-z0-9][A-Za-z0-9\-]*)*:\/.*|\/.*)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/power/power.schema
wakemode: function(value, element) {
	return this.optional(element) || /^(none|magic)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/power/power.schema
powermode: function(value, element) {
	return this.optional(element) || /^(on|off|same)$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/telnet/telnet.schema
telnetaccess: function(value, element) {
	return this.optional(element) || /none|root|reg/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/ssl/ssl.schema
sslCountry: function(value, element) {
	return this.optional(element) || /^[A-Z]{2}$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/mailman/MailMan.schema
postPolicy: function(value, element) {
	return this.optional(element) ||
/^((moderated)|(any)|(members))?$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/mailman/MailMan.schema
subPolicy: function(value, element) {
	return this.optional(element) ||
/^((closed)|(open)|(confirm))?$/.test(value);
},
// BlueOnyx Rule: /usr/sausalito/schemas/base/mailman/MailMan.schema
mailman_name: function(value, element) {
	return this.optional(element) || /^[a-z0-9_\-][a-z0-9_\.\-]*$/.test(value);
}		

Just a quick note on that 5200R code: It has a few more "typedefs" than
510XR. Any rule that says "multiline" or where the name indicates that
it's a duplicate of something ("hostname" vs. "hostnames" for example)
is new. For 5200R I had to create these duplicates to verify input based
on if we check just for one instance of the data, or for multiple
instances such as five entered "ipaddr" in one large textarea.

-- 

With best regards

Michael Stauber



More information about the Blueonyx mailing list